summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2004-07-20 00:53:24 +0200
committerunknown <serg@serg.mylan>2004-07-20 00:53:24 +0200
commiteee5f15b92f71c74ce315932770a603e4deef477 (patch)
treeb39cfbb54d66b05cd075839aa58dc3215c8d4146 /innobase
parentd57d78ac10980e28344f285bdbc986fa3ee3496e (diff)
parentb940ae1012b00e74e2155c4e35ca7872bed278e3 (diff)
downloadmariadb-git-eee5f15b92f71c74ce315932770a603e4deef477.tar.gz
manual merged (blame me!)
Build-tools/Do-compile: Auto merged Docs/Makefile.am: Auto merged innobase/btr/btr0cur.c: Auto merged innobase/include/lock0lock.h: Auto merged innobase/include/row0mysql.h: Auto merged innobase/include/srv0srv.h: Auto merged innobase/include/sync0arr.h: Auto merged innobase/include/trx0trx.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/sync/sync0arr.c: Auto merged innobase/trx/trx0trx.c: Auto merged sql/ha_innodb.cc: Auto merged sql/sql_insert.cc: Auto merged mysql-test/r/innodb.result: to be fixed after the merge
Diffstat (limited to 'innobase')
-rw-r--r--innobase/btr/btr0cur.c11
-rw-r--r--innobase/include/lock0lock.h5
-rw-r--r--innobase/include/row0mysql.h7
-rw-r--r--innobase/include/srv0srv.h1
-rw-r--r--innobase/include/sync0arr.h2
-rw-r--r--innobase/include/trx0trx.h5
-rw-r--r--innobase/lock/lock0lock.c40
-rw-r--r--innobase/row/row0ins.c81
-rw-r--r--innobase/row/row0mysql.c21
-rw-r--r--innobase/srv/srv0srv.c3
-rw-r--r--innobase/srv/srv0start.c2
-rw-r--r--innobase/sync/sync0arr.c12
-rw-r--r--innobase/trx/trx0trx.c4
13 files changed, 138 insertions, 56 deletions
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 2e9194ff30f..be201da4510 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -2717,8 +2717,11 @@ btr_estimate_number_of_different_key_vals(
rec = page_rec_get_next(rec);
}
+
if (n_cols == dict_index_get_n_unique_in_tree(index)) {
- /* We add one because we know that the first record
+
+ /* If there is more than one leaf page in the tree,
+ we add one because we know that the first record
on the page certainly had a different prefix than the
last record on the previous index page in the
alphabetical order. Before this fix, if there was
@@ -2726,7 +2729,11 @@ btr_estimate_number_of_different_key_vals(
algorithm grossly underestimated the number of rows
in the table. */
- n_diff[n_cols]++;
+ if (btr_page_get_prev(page, &mtr) != FIL_NULL
+ || btr_page_get_next(page, &mtr) != FIL_NULL) {
+
+ n_diff[n_cols]++;
+ }
}
total_external_size +=
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 9c5f35c6674..9f525042dcc 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -418,7 +418,8 @@ lock_release_off_kernel(
/*====================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
-Releases table locks, and releases possible other transactions waiting
+Releases table locks explicitly requested with LOCK TABLES (indicated by
+lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
because of these locks. */
void
@@ -548,7 +549,7 @@ extern lock_sys_t* lock_sys;
/* Lock types */
#define LOCK_TABLE 16 /* these type values should be so high that */
#define LOCK_REC 32 /* they can be ORed to the lock mode */
-#define LOCK_TABLE_EXP 80 /* explicit table lock */
+#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
type_mode field in a lock */
/* Waiting lock flag */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 390e8c4da57..8f6264944ce 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -161,11 +161,12 @@ row_lock_table_autoinc_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
table handle */
/*************************************************************************
-Unlocks a table lock possibly reserved by trx. */
+Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
+lock type LOCK_TABLE_EXP). */
void
-row_unlock_table_for_mysql(
-/*=======================*/
+row_unlock_tables_for_mysql(
+/*========================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index c527d40bc79..c7ba39aaaf1 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -157,6 +157,7 @@ extern ulint srv_test_n_mutexes;
extern ulint srv_test_array_size;
extern ulint srv_activity_count;
+extern ulint srv_fatal_semaphore_wait_threshold;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
query threads, and lock table: we allocate
diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h
index e7d511f8137..92691d5fdd9 100644
--- a/innobase/include/sync0arr.h
+++ b/innobase/include/sync0arr.h
@@ -95,7 +95,7 @@ void
sync_arr_wake_threads_if_sema_free(void);
/*====================================*/
/**************************************************************************
-Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */
+Prints warnings of long semaphore waits to stderr. */
void
sync_array_print_long_waits(void);
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index a8c1df534da..7eb91048684 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -423,8 +423,9 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
- ulint n_tables_locked;/* number of table locks reserved by
- the transaction, stored in trx_locks */
+ ulint n_lock_table_exp;/* number of explicit table locks
+ (LOCK TABLES) reserved by the
+ transaction, stored in trx_locks */
UT_LIST_NODE_T(trx_t)
trx_list; /* list of transactions */
UT_LIST_NODE_T(trx_t)
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index be0806590a9..92e8f224dea 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -2023,9 +2023,8 @@ lock_grant(
lock->trx->auto_inc_lock = lock;
} else if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_ad(lock_get_mode(lock) == LOCK_S
+ ut_a(lock_get_mode(lock) == LOCK_S
|| lock_get_mode(lock) == LOCK_X);
- lock->trx->n_tables_locked++;
}
if (lock_print_waits) {
@@ -3203,6 +3202,10 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ lock->trx->n_lock_table_exp++;
+ }
+
lock->un_member.tab_lock.table = table;
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
@@ -3238,7 +3241,11 @@ lock_table_remove_low(
if (lock == trx->auto_inc_lock) {
trx->auto_inc_lock = NULL;
}
-
+
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ lock->trx->n_lock_table_exp--;
+ }
+
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
}
@@ -3386,7 +3393,7 @@ lock_table(
return(DB_SUCCESS);
}
- ut_ad(flags == 0 || flags == LOCK_TABLE_EXP);
+ ut_a(flags == 0 || flags == LOCK_TABLE_EXP);
trx = thr_get_trx(thr);
@@ -3418,10 +3425,7 @@ lock_table(
lock_table_create(table, mode | flags, trx);
- if (flags) {
- ut_ad(mode == LOCK_S || mode == LOCK_X);
- trx->n_tables_locked++;
- }
+ ut_a(!flags || mode == LOCK_S || mode == LOCK_X);
lock_mutex_exit_kernel();
@@ -3502,13 +3506,13 @@ lock_table_dequeue(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(lock_get_type(in_lock) == LOCK_TABLE ||
+ ut_a(lock_get_type(in_lock) == LOCK_TABLE ||
lock_get_type(in_lock) == LOCK_TABLE_EXP);
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
lock_table_remove_low(in_lock);
-
+
/* Check if waiting locks in the queue can now be granted: grant
locks if there are no conflicting locks ahead. */
@@ -3608,9 +3612,8 @@ lock_release_off_kernel(
lock_table_dequeue(lock);
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_ad(lock_get_mode(lock) == LOCK_S
+ ut_a(lock_get_mode(lock) == LOCK_S
|| lock_get_mode(lock) == LOCK_X);
- trx->n_tables_locked--;
}
}
@@ -3631,11 +3634,12 @@ lock_release_off_kernel(
mem_heap_empty(trx->lock_heap);
ut_a(trx->auto_inc_lock == NULL);
- ut_a(trx->n_tables_locked == 0);
+ ut_a(trx->n_lock_table_exp == 0);
}
/*************************************************************************
-Releases table locks, and releases possible other transactions waiting
+Releases table locks explicitly requested with LOCK TABLES (indicated by
+lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
because of these locks. */
void
@@ -3660,7 +3664,7 @@ lock_release_tables_off_kernel(
count++;
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_ad(lock_get_mode(lock) == LOCK_S
+ ut_a(lock_get_mode(lock) == LOCK_S
|| lock_get_mode(lock) == LOCK_X);
if (trx->insert_undo || trx->update_undo) {
@@ -3676,7 +3680,7 @@ lock_release_tables_off_kernel(
}
lock_table_dequeue(lock);
- trx->n_tables_locked--;
+
lock = UT_LIST_GET_LAST(trx->trx_locks);
continue;
}
@@ -3695,9 +3699,7 @@ lock_release_tables_off_kernel(
lock = UT_LIST_GET_PREV(trx_locks, lock);
}
- mem_heap_empty(trx->lock_heap);
-
- ut_a(trx->n_tables_locked == 0);
+ ut_a(trx->n_lock_table_exp == 0);
}
/*************************************************************************
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 7f1852c70f2..0da749212d2 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -370,6 +370,32 @@ row_ins_cascade_ancestor_updates_table(
return(FALSE);
}
+/*************************************************************************
+Returns the number of ancestor UPDATE or DELETE nodes of a
+cascaded update/delete node. */
+static
+ulint
+row_ins_cascade_n_ancestors(
+/*========================*/
+ /* out: number of ancestors */
+ que_node_t* node) /* in: node in a query graph */
+{
+ que_node_t* parent;
+ ulint n_ancestors = 0;
+
+ parent = que_node_get_parent(node);
+
+ while (que_node_get_type(parent) == QUE_NODE_UPDATE) {
+ n_ancestors++;
+
+ parent = que_node_get_parent(parent);
+
+ ut_a(parent);
+ }
+
+ return(n_ancestors);
+}
+
/**********************************************************************
Calculates the update vector node->cascade->update for a child table in
a cascaded update. */
@@ -616,6 +642,34 @@ row_ins_foreign_report_add_err(
}
/*************************************************************************
+Invalidate the query cache for the given table. */
+static
+void
+row_ins_invalidate_query_cache(
+/*===========================*/
+ que_thr_t* thr, /* in: query thread whose run_node
+ is an update node */
+ const char* name) /* in: table name prefixed with
+ database name and a '/' character */
+{
+ char* buf;
+ char* ptr;
+ ulint len = strlen(name) + 1;
+
+ buf = mem_strdupl(name, len);
+
+ ptr = strchr(buf, '/');
+ ut_a(ptr);
+ *ptr = '\0';
+
+ /* We call a function in ha_innodb.cc */
+#ifndef UNIV_HOTBACKUP
+ innobase_invalidate_query_cache(thr_get_trx(thr), buf, len);
+#endif
+ mem_free(buf);
+}
+
+/*************************************************************************
Perform referential actions or checks when a parent row is deleted or updated
and the constraint had an ON DELETE or ON UPDATE condition which was not
RESTRICT. */
@@ -650,26 +704,15 @@ row_ins_foreign_check_on_constraint(
ulint n_to_update;
ulint err;
ulint i;
- char* ptr;
- char* table_name_buf;
+
+
ut_a(thr && foreign && pcur && mtr);
/* Since we are going to delete or update a row, we have to invalidate
the MySQL query cache for table */
- table_name_buf = mem_strdup(table->name);
-
- ptr = strchr(table_name_buf, '/');
- ut_a(ptr);
- *ptr = '\0';
-
-#ifndef UNIV_HOTBACKUP
- /* We call a function in ha_innodb.cc */
- innobase_invalidate_query_cache(thr_get_trx(thr), table_name_buf,
- strlen(table->name) + 1);
-#endif
- mem_free(table_name_buf);
+ row_ins_invalidate_query_cache(thr, table->name);
node = thr->run_node;
@@ -757,6 +800,16 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
+ if (row_ins_cascade_n_ancestors(cascade) >= 15) {
+ err = DB_ROW_IS_REFERENCED;
+
+ row_ins_foreign_report_err(
+(char*)"Trying a too deep cascaded delete or update\n",
+ thr, foreign, btr_pcur_get_rec(pcur), entry);
+
+ goto nonstandard_exit_func;
+ }
+
index = btr_pcur_get_btr_cur(pcur)->index;
ut_a(index == foreign->foreign_index);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index c4408de2a85..556c80c948d 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -741,14 +741,15 @@ run_again:
}
/*************************************************************************
-Unlocks a table lock possibly reserved by trx. */
+Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
+lock type LOCK_TABLE_EXP). */
void
-row_unlock_table_for_mysql(
-/*=======================*/
+row_unlock_tables_for_mysql(
+/*========================*/
trx_t* trx) /* in: transaction */
{
- if (!trx->n_tables_locked) {
+ if (!trx->n_lock_table_exp) {
return;
}
@@ -3175,7 +3176,12 @@ row_check_table_for_mysql(
REPEATABLE READ here */
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
-
+
+ /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -3223,6 +3229,11 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
+ /* Restore the fatal lock wait timeout after CHECK TABLE. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
prebuilt->trx->op_info = "";
return(ret);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index fc46c95a8a6..4bc5b0dc795 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -55,6 +55,9 @@ ibool srv_lower_case_table_names = FALSE;
in the server */
ulint srv_activity_count = 0;
+/* The following is the maximum allowed duration of a lock wait. */
+ulint srv_fatal_semaphore_wait_threshold = 600;
+
ibool srv_lock_timeout_and_monitor_active = FALSE;
ibool srv_error_monitor_active = FALSE;
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index dd38eddb20b..74dd23e4252 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1115,7 +1115,7 @@ NetWare. */
srv_monitor_file_name = mem_alloc(
strlen(fil_path_to_mysql_datadir) +
20 + sizeof "/innodb_status.");
- sprintf(srv_monitor_file_name, "%s/innodb.status.%lu",
+ sprintf(srv_monitor_file_name, "%s/innodb_status.%lu",
fil_path_to_mysql_datadir, os_proc_get_number());
srv_monitor_file = fopen(srv_monitor_file_name, "w+");
if (!srv_monitor_file) {
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index d1644412fbb..7cd221df6a5 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -895,7 +895,7 @@ sync_arr_wake_threads_if_sema_free(void)
}
/**************************************************************************
-Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */
+Prints warnings of long semaphore waits to stderr. */
void
sync_array_print_long_waits(void)
@@ -905,6 +905,7 @@ sync_array_print_long_waits(void)
ibool old_val;
ibool noticed = FALSE;
ulint i;
+ ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
@@ -919,12 +920,13 @@ sync_array_print_long_waits(void)
}
if (cell->wait_object != NULL
- && difftime(time(NULL), cell->reservation_time) > 600) {
+ && difftime(time(NULL), cell->reservation_time)
+ > fatal_timeout) {
- fputs(
-"InnoDB: Error: semaphore wait has lasted > 600 seconds\n"
+ fprintf(stderr,
+"InnoDB: Error: semaphore wait has lasted > %lu seconds\n"
"InnoDB: We intentionally crash the server, because it appears to be hung.\n",
- stderr);
+ fatal_timeout);
ut_error;
}
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index a9aae48dae6..f7497ac4090 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -151,7 +151,7 @@ trx_create(
trx->n_tickets_to_enter_innodb = 0;
trx->auto_inc_lock = NULL;
- trx->n_tables_locked = 0;
+ trx->n_lock_table_exp = 0;
trx->read_view_heap = mem_heap_create(256);
trx->read_view = NULL;
@@ -279,7 +279,7 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
- ut_a(!trx->n_tables_locked);
+ ut_a(!trx->n_lock_table_exp);
ut_a(trx->dict_operation_lock_mode == 0);