summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2002-11-06 00:41:27 +0200
committerunknown <heikki@hundin.mysql.fi>2002-11-06 00:41:27 +0200
commit444d8207d9a277231733dc6cd58bf21b626bba31 (patch)
treefed8334ab45443418d527c3837593e1121ed1975 /innobase
parent23f4865b163293006bbedbc2b69bc55ba1081baa (diff)
downloadmariadb-git-444d8207d9a277231733dc6cd58bf21b626bba31.tar.gz
Many files:
Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock sql/ha_innodb.cc: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/dict/dict0crea.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/dict/dict0dict.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/log0recv.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/row0mysql.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/srv0srv.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/include/trx0trx.h: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/log/log0recv.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/os/os0sync.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/os/os0thread.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0ins.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0mysql.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0purge.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0undo.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/row/row0upd.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/srv/srv0srv.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/srv/srv0start.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/trx/trx0roll.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock innobase/trx/trx0trx.c: Merge InnoDB-4.0.5b: minor improvements to foreign keys, more logical data dictionary lock
Diffstat (limited to 'innobase')
-rw-r--r--innobase/dict/dict0crea.c18
-rw-r--r--innobase/dict/dict0dict.c219
-rw-r--r--innobase/include/log0recv.h1
-rw-r--r--innobase/include/row0mysql.h39
-rw-r--r--innobase/include/srv0srv.h3
-rw-r--r--innobase/include/trx0trx.h63
-rw-r--r--innobase/log/log0recv.c20
-rw-r--r--innobase/os/os0sync.c10
-rw-r--r--innobase/os/os0thread.c13
-rw-r--r--innobase/row/row0ins.c13
-rw-r--r--innobase/row/row0mysql.c98
-rw-r--r--innobase/row/row0purge.c30
-rw-r--r--innobase/row/row0undo.c20
-rw-r--r--innobase/row/row0upd.c28
-rw-r--r--innobase/srv/srv0srv.c17
-rw-r--r--innobase/srv/srv0start.c16
-rw-r--r--innobase/trx/trx0roll.c8
-rw-r--r--innobase/trx/trx0trx.c4
18 files changed, 444 insertions, 176 deletions
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 60beeacf435..b0f84e5663a 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1041,7 +1041,7 @@ dict_create_or_check_foreign_constraint_tables(void)
que_t* graph;
ulint error;
trx_t* trx;
- char* str;
+ char* str;
mutex_enter(&(dict_sys->mutex));
@@ -1060,20 +1060,24 @@ dict_create_or_check_foreign_constraint_tables(void)
return(DB_SUCCESS);
}
+ mutex_exit(&(dict_sys->mutex));
+
trx = trx_allocate_for_mysql();
trx->op_info = (char *) "creating foreign key sys tables";
+ row_mysql_lock_data_dictionary(trx);
+
if (table1) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
}
fprintf(stderr,
@@ -1122,8 +1126,8 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
@@ -1132,6 +1136,8 @@ dict_create_or_check_foreign_constraint_tables(void)
trx->op_info = (char *) "";
+ row_mysql_unlock_data_dictionary(trx);
+
trx_free_for_mysql(trx);
if (error == DB_SUCCESS) {
@@ -1139,8 +1145,6 @@ dict_create_or_check_foreign_constraint_tables(void)
"InnoDB: Foreign key constraint system tables created\n");
}
- mutex_exit(&(dict_sys->mutex));
-
return(error);
}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 2ee2c9d18a9..18f27602cf0 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -30,13 +30,16 @@ Created 1/8/1996 Heikki Tuuri
dict_sys_t* dict_sys = NULL; /* the dictionary system */
rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
- this in X-mode, implicit or backround
+ this in X-mode; implicit or backround
operations purge, rollback, foreign
key checks reserve this in S-mode; we
cannot trust that MySQL protects
implicit or background operations
- from dropping a table: this is our
- mechanism */
+ a table drop since MySQL does not
+ know of them; therefore we need this;
+ NOTE: a transaction which reserves
+ this must keep book on the mode in
+ trx->dict_operation_lock_mode */
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
creating a table or index object */
@@ -183,6 +186,58 @@ dict_foreign_free(
dict_foreign_t* foreign); /* in, own: foreign key struct */
/************************************************************************
+Checks if the database name in two table names is the same. */
+static
+ibool
+dict_tables_have_same_db(
+/*=====================*/
+ /* out: TRUE if same db name */
+ char* name1, /* in: table name in the form dbname '/' tablename */
+ char* name2) /* in: table name in the form dbname '/' tablename */
+{
+ ulint i;
+
+ for (i = 0; i < 100000; i++) {
+ if (name1[i] == '/' && name2[i] == '/') {
+
+ return(TRUE);
+ }
+
+ if (name1[i] != name2[i]) {
+
+ return(FALSE);
+ }
+ }
+
+ ut_a(0);
+
+ return(FALSE);
+}
+
+/************************************************************************
+Return the end of table name where we have removed dbname and '/'. */
+static
+char*
+dict_remove_db_name(
+/*================*/
+ /* out: table name */
+ char* name) /* in: table name in the form dbname '/' tablename */
+{
+ ulint i;
+
+ for (i = 0; i < 100000 ; i++) {
+ if (name[i] == '/') {
+
+ return(name + i + 1);
+ }
+ }
+
+ ut_a(0);
+
+ return(NULL);
+}
+
+/************************************************************************
Reserves the dictionary system mutex for MySQL. */
void
@@ -1926,7 +1981,8 @@ dict_scan_col(
old_ptr = ptr;
- while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') {
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`'
+ && *ptr != '\0') {
ptr++;
}
@@ -2000,7 +2056,7 @@ dict_scan_table_name(
old_ptr = ptr;
- while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
+ while (!isspace(*ptr) && *ptr != '(' && *ptr != '`' && *ptr != '\0') {
if (*ptr == '.') {
dot_ptr = ptr;
}
@@ -2023,17 +2079,28 @@ dict_scan_table_name(
}
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
- ptr - old_ptr);
+ ptr - old_ptr);
#else
- ut_memcpy(second_table_name + i, old_ptr, ptr - old_ptr);
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name + i, old_ptr,
+ ptr - old_ptr);
+ } else {
+ ut_memcpy(second_table_name + i, old_ptr,
+ ptr - old_ptr);
+ }
#endif
second_table_name[i + (ptr - old_ptr)] = '\0';
} else {
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name, old_ptr,
- ptr - old_ptr);
+ ptr - old_ptr);
#else
- ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name, old_ptr,
+ ptr - old_ptr);
+ } else {
+ ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ }
#endif
second_table_name[dot_ptr - old_ptr] = '/';
second_table_name[ptr - old_ptr] = '\0';
@@ -2051,6 +2118,44 @@ dict_scan_table_name(
}
/*************************************************************************
+Skips one 'word', like an id. For the lexical definition of 'word', see the
+code below. */
+static
+char*
+dict_skip_word(
+/*===========*/
+ /* out: scanned to */
+ char* ptr, /* in: scanned to */
+ ibool* success)/* out: TRUE if success, FALSE if just spaces left in
+ string */
+{
+ *success = FALSE;
+
+ while (isspace(*ptr)) {
+ ptr++;
+ }
+
+ if (*ptr == '\0') {
+
+ return(ptr);
+ }
+
+ if (*ptr == '`') {
+ ptr++;
+ }
+
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
+ && *ptr != '\0') {
+
+ ptr++;
+ }
+
+ *success = TRUE;
+
+ return(ptr);
+}
+
+/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
static
@@ -2119,7 +2224,6 @@ dict_create_foreign_constraints(
if (table == NULL) {
return(DB_ERROR);
}
-
loop:
ptr = dict_scan_to(ptr, (char *) "FOREIGN");
@@ -2148,7 +2252,19 @@ loop:
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
- goto loop;
+ /* MySQL allows also an index id before the '('; we
+ skip it */
+ ptr = dict_skip_word(ptr, &success);
+
+ if (!success) {
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ ptr = dict_accept(ptr, (char *) "(", &success);
+
+ if (!success) {
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
}
i = 0;
@@ -2223,6 +2339,7 @@ col_loop1:
if (!success) {
dict_foreign_free(foreign);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2236,6 +2353,7 @@ col_loop2:
if (!success) {
dict_foreign_free(foreign);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2263,14 +2381,20 @@ col_loop2:
ptr = dict_accept(ptr, "DELETE", &success);
if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ ptr = dict_accept(ptr, "RESTRICT", &success);
+ if (success) {
goto try_find_index;
}
ptr = dict_accept(ptr, "CASCADE", &success);
if (success) {
-
foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;
goto try_find_index;
@@ -2279,32 +2403,47 @@ col_loop2:
ptr = dict_accept(ptr, "SET", &success);
if (!success) {
-
- goto try_find_index;
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, "NULL", &success);
- if (success) {
- for (j = 0; j < foreign->n_fields; j++) {
- if ((dict_index_get_nth_type(
+ if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ for (j = 0; j < foreign->n_fields; j++) {
+ if ((dict_index_get_nth_type(
foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
- /* It is not sensible to define SET NULL
- if the column is not allowed to be NULL! */
+ /* It is not sensible to define SET NULL
+ if the column is not allowed to be NULL! */
- dict_foreign_free(foreign);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
+ }
- foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+ foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+
+try_find_index:
+ /* We check that there are no superfluous words like 'ON UPDATE ...'
+ which we do not support yet. */
- goto try_find_index;
+ ptr = dict_accept(ptr, (char *) "ON", &success);
+
+ if (success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
-try_find_index:
/* Try to find an index which contains the columns as the first fields
and in the right order, and the types are the same as in
foreign->foreign_index */
@@ -2351,6 +2490,7 @@ try_find_index:
referenced_table->referenced_list,
foreign);
}
+
goto loop;
}
@@ -2849,6 +2989,14 @@ dict_update_statistics_low(
ulint size;
ulint sum_of_index_sizes = 0;
+ /* If we have set a high innodb_force_recovery level, do not calculate
+ statistics, as a badly corrupted index can cause a crash in it. */
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ return;
+ }
+
/* Find out the sizes of the indexes and how many different values
for the key they approximately have */
@@ -3152,16 +3300,25 @@ dict_print_info_on_foreign_keys_in_create_format(
}
}
- buf2 += sprintf(buf2, ") REFERENCES `%s` (",
+ if (dict_tables_have_same_db(table->name,
+ foreign->referenced_table_name)) {
+ /* Do not print the database name of the referenced
+ table */
+ buf2 += sprintf(buf2, ") REFERENCES `%s` (",
+ dict_remove_db_name(
+ foreign->referenced_table_name));
+ } else {
+ buf2 += sprintf(buf2, ") REFERENCES `%s` (",
foreign->referenced_table_name);
- /* Change the '/' in the table name to '.' */
+ /* Change the '/' in the table name to '.' */
- for (i = ut_strlen(buf); i > 0; i--) {
- if (buf[i] == '/') {
+ for (i = ut_strlen(buf); i > 0; i--) {
+ if (buf[i] == '/') {
- buf[i] = '.';
+ buf[i] = '.';
- break;
+ break;
+ }
}
}
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index baa2ba50c7d..7418e4abf1b 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -334,6 +334,7 @@ extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
extern ibool recv_is_making_a_backup;
+extern ulint recv_max_parsed_page_no;
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
times! */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 8152c534f48..c72c905edf5 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -230,18 +230,35 @@ row_update_cascade_for_mysql(
or set null operation */
dict_table_t* table); /* in: table where we do the operation */
/*************************************************************************
-Locks the data dictionary exclusively for performing a table create
-operation. */
+Locks the data dictionary exclusively for performing a table create or other
+data dictionary modification operation. */
void
-row_mysql_lock_data_dictionary(void);
-/*================================*/
+row_mysql_lock_data_dictionary(
+/*===========================*/
+ trx_t* trx); /* in: transaction */
/*************************************************************************
-Unlocks the data dictionary exclusively lock. */
+Unlocks the data dictionary exclusive lock. */
void
-row_mysql_unlock_data_dictionary(void);
-/*==================================*/
+row_mysql_unlock_data_dictionary(
+/*=============================*/
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
+Locks the data dictionary in shared mode from modifications, for performing
+foreign key check, rollback, or other operation invisible to MySQL. */
+
+void
+row_mysql_freeze_data_dictionary(
+/*=============================*/
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
+Unlocks the data dictionary shared lock. */
+
+void
+row_mysql_unfreeze_data_dictionary(
+/*===============================*/
+ trx_t* trx); /* in: transaction */
/*************************************************************************
Does a table creation operation for MySQL. If the name of the created
table ends to characters INNODB_MONITOR, then this also starts
@@ -310,11 +327,9 @@ output by the master thread. */
int
row_drop_table_for_mysql(
/*=====================*/
- /* out: error code or DB_SUCCESS */
- char* name, /* in: table name */
- trx_t* trx, /* in: transaction handle */
- ibool has_dict_mutex);/* in: TRUE if the caller already owns the
- dictionary system mutex */
+ /* out: error code or DB_SUCCESS */
+ char* name, /* in: table name */
+ trx_t* trx); /* in: transaction handle */
/*************************************************************************
Drops a database for MySQL. */
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 4d2768cf109..ad6f71f7a3a 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -28,6 +28,9 @@ extern os_event_t srv_lock_timeout_thread_event;
at a time */
#define SRV_AUTO_EXTEND_INCREMENT (8 * ((1024 * 1024) / UNIV_PAGE_SIZE))
+/* This is set to TRUE if the MySQL user has set it in MySQL */
+extern ibool srv_lower_case_table_names;
+
/* Server parameters which are read from the initfile */
extern char* srv_data_home;
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 874b126e47c..1468ef449e7 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -386,9 +386,10 @@ struct trx_struct{
/* how many tables the current SQL
statement uses, except those
in consistent read */
- ibool has_dict_operation_lock;
- /* TRUE if the trx currently holds
- an s-lock on dict_operation_lock */
+ ibool dict_operation_lock_mode;
+ /* 0, RW_S_LATCH, or RW_X_LATCH:
+ the latch mode trx currently holds
+ on dict_operation_lock */
ibool has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
@@ -427,34 +428,6 @@ struct trx_struct{
mysql_trx_list; /* list of transactions created for
MySQL */
/*------------------------------*/
- mutex_t undo_mutex; /* mutex protecting the fields in this
- section (down to undo_no_arr), EXCEPT
- last_sql_stat_start, which can be
- accessed only when we know that there
- cannot be any activity in the undo
- logs! */
- dulint undo_no; /* next undo log record number to
- assign */
- trx_savept_t last_sql_stat_start;
- /* undo_no when the last sql statement
- was started: in case of an error, trx
- is rolled back down to this undo
- number; see note at undo_mutex! */
- trx_rseg_t* rseg; /* rollback segment assigned to the
- transaction, or NULL if not assigned
- yet */
- trx_undo_t* insert_undo; /* pointer to the insert undo log, or
- NULL if no inserts performed yet */
- trx_undo_t* update_undo; /* pointer to the update undo log, or
- NULL if no update performed yet */
- dulint roll_limit; /* least undo number to undo during
- a rollback */
- ulint pages_undone; /* number of undo log pages undone
- since the last undo log truncation */
- trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
- records which are currently processed
- by a rollback operation */
- /*------------------------------*/
ulint error_state; /* 0 if no error, otherwise error
number */
void* error_info; /* if the error number indicates a
@@ -508,6 +481,34 @@ struct trx_struct{
/*------------------------------*/
mem_heap_t* read_view_heap; /* memory heap for the read view */
read_view_t* read_view; /* consistent read view or NULL */
+ /*------------------------------*/
+ mutex_t undo_mutex; /* mutex protecting the fields in this
+ section (down to undo_no_arr), EXCEPT
+ last_sql_stat_start, which can be
+ accessed only when we know that there
+ cannot be any activity in the undo
+ logs! */
+ dulint undo_no; /* next undo log record number to
+ assign */
+ trx_savept_t last_sql_stat_start;
+ /* undo_no when the last sql statement
+ was started: in case of an error, trx
+ is rolled back down to this undo
+ number; see note at undo_mutex! */
+ trx_rseg_t* rseg; /* rollback segment assigned to the
+ transaction, or NULL if not assigned
+ yet */
+ trx_undo_t* insert_undo; /* pointer to the insert undo log, or
+ NULL if no inserts performed yet */
+ trx_undo_t* update_undo; /* pointer to the update undo log, or
+ NULL if no update performed yet */
+ dulint roll_limit; /* least undo number to undo during
+ a rollback */
+ ulint pages_undone; /* number of undo log pages undone
+ since the last undo log truncation */
+ trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
+ records which are currently processed
+ by a rollback operation */
};
#define TRX_MAX_N_THREADS 32 /* maximum number of concurrent
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 1223f9b6041..0fcf32ad99e 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -69,6 +69,8 @@ ulint recv_previous_parsed_rec_type = 999999;
ulint recv_previous_parsed_rec_offset = 0;
ulint recv_previous_parsed_rec_is_multi = 0;
+ulint recv_max_parsed_page_no = 0;
+
/************************************************************
Creates the recovery system. */
@@ -141,7 +143,13 @@ recv_sys_empty_hash(void)
/*=====================*/
{
ut_ad(mutex_own(&(recv_sys->mutex)));
- ut_a(recv_sys->n_addrs == 0);
+ if (recv_sys->n_addrs != 0) {
+ fprintf(stderr,
+"InnoDB: Error: %lu pages with log records were left unprocessed!\n"
+"InnoDB: Maximum page number with log records on it %lu\n",
+ recv_sys->n_addrs, recv_max_parsed_page_no);
+ ut_a(0);
+ }
hash_table_free(recv_sys->addr_hash);
mem_heap_empty(recv_sys->heap);
@@ -1361,6 +1369,12 @@ recv_apply_log_recs_for_backup(
n_pages_total += file_sizes[i];
}
+ if (recv_max_parsed_page_no >= n_pages_total) {
+ printf(
+"InnoDB: Error: tablespace size %lu pages, but a log record on page %lu!\n",
+ n_pages_total, recv_max_parsed_page_no);
+ }
+
printf(
"InnoDB: Starting an apply batch of log records to the database...\n"
"InnoDB: Progress in percents: ");
@@ -1701,6 +1715,10 @@ recv_parse_log_rec(
return(0);
}
+ if (*page_no > recv_max_parsed_page_no) {
+ recv_max_parsed_page_no = *page_no;
+ }
+
return(new_ptr - ptr);
}
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 14677ede20f..bac1f23a1af 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -66,8 +66,12 @@ os_event_create(
event = ut_malloc(sizeof(struct os_event_struct));
os_fast_mutex_init(&(event->os_mutex));
- pthread_cond_init(&(event->cond_var), NULL);
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ pthread_cond_init(&(event->cond_var), pthread_condattr_default);
+#else
+ pthread_cond_init(&(event->cond_var), NULL);
+#endif
event->is_set = FALSE;
return(event);
@@ -441,8 +445,12 @@ os_fast_mutex_init(
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ pthread_mutex_init(fast_mutex, pthread_mutexattr_default);
+#else
pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
#endif
+#endif
}
/**************************************************************
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 48aea4b8abb..30404c4e66b 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -126,8 +126,10 @@ os_thread_create(
os_thread_t pthread;
pthread_attr_t attr;
+#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
pthread_attr_init(&attr);
-
+#endif
+
#ifdef UNIV_AIX
/* We must make sure a thread stack is at least 32 kB, otherwise
InnoDB might crash; we do not know if the default stack size on
@@ -142,16 +144,21 @@ os_thread_create(
exit(1);
}
#endif
- ret = pthread_create(&pthread, &attr, start_f, arg);
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
+#else
+ ret = pthread_create(&pthread, &attr, start_f, arg);
+#endif
if (ret) {
fprintf(stderr,
"InnoDB: Error: pthread_create returned %d\n", ret);
exit(1);
}
+#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
pthread_attr_destroy(&attr);
-
+#endif
if (srv_set_thread_priorities) {
my_pthread_setprio(pthread, srv_query_thread_priority);
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 4e8b487a0f1..d0a5cfec604 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -643,7 +643,7 @@ row_ins_check_foreign_constraint(
run_again:
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED));
-
+
err = DB_SUCCESS;
if (thr_get_trx(thr)->check_foreigns == FALSE) {
@@ -880,21 +880,16 @@ row_ins_check_foreign_constraints(
trx);
}
- if (!trx->has_dict_operation_lock) {
+ if (0 == trx->dict_operation_lock_mode) {
got_s_lock = TRUE;
- rw_lock_s_lock(&dict_operation_lock);
-
- trx->has_dict_operation_lock = TRUE;
+ row_mysql_freeze_data_dictionary(trx);
}
err = row_ins_check_foreign_constraint(TRUE, foreign,
table, index, entry, thr);
if (got_s_lock) {
-
- rw_lock_s_unlock(&dict_operation_lock);
-
- trx->has_dict_operation_lock = FALSE;
+ row_mysql_unfreeze_data_dictionary(trx);
}
if (err != DB_SUCCESS) {
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 6fde57eb75a..b109b785a45 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1134,32 +1134,73 @@ row_mysql_recover_tmp_table(
}
/*************************************************************************
-Locks the data dictionary exclusively for performing a table create
-operation. */
+Locks the data dictionary in shared mode from modifications, for performing
+foreign key check, rollback, or other operation invisible to MySQL. */
void
-row_mysql_lock_data_dictionary(void)
-/*================================*/
+row_mysql_freeze_data_dictionary(
+/*=============================*/
+ trx_t* trx) /* in: transaction */
+{
+ ut_a(trx->dict_operation_lock_mode == 0);
+
+ rw_lock_s_lock(&dict_operation_lock);
+
+ trx->dict_operation_lock_mode = RW_S_LATCH;
+}
+
+/*************************************************************************
+Unlocks the data dictionary shared lock. */
+
+void
+row_mysql_unfreeze_data_dictionary(
+/*===============================*/
+ trx_t* trx) /* in: transaction */
{
+ ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
+
+ rw_lock_s_unlock(&dict_operation_lock);
+
+ trx->dict_operation_lock_mode = 0;
+}
+
+/*************************************************************************
+Locks the data dictionary exclusively for performing a table create or other
+data dictionary modification operation. */
+
+void
+row_mysql_lock_data_dictionary(
+/*===========================*/
+ trx_t* trx) /* in: transaction */
+{
+ ut_a(trx->dict_operation_lock_mode == 0);
+
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks or lock waits can occur then in these operations */
rw_lock_x_lock(&dict_operation_lock);
+ trx->dict_operation_lock_mode = RW_X_LATCH;
+
mutex_enter(&(dict_sys->mutex));
}
/*************************************************************************
-Unlocks the data dictionary exclusively lock. */
+Unlocks the data dictionary exclusive lock. */
void
-row_mysql_unlock_data_dictionary(void)
-/*==================================*/
+row_mysql_unlock_data_dictionary(
+/*=============================*/
+ trx_t* trx) /* in: transaction */
{
+ ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
+
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
mutex_exit(&(dict_sys->mutex));
rw_lock_x_unlock(&dict_operation_lock);
+
+ trx->dict_operation_lock_mode = 0;
}
/*************************************************************************
@@ -1183,6 +1224,7 @@ row_create_table_for_mysql(
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+ ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&(dict_sys->mutex)));
if (srv_created_new_raw) {
@@ -1331,7 +1373,7 @@ row_create_table_for_mysql(
fprintf(stderr,
"InnoDB: Warning: cannot create table %s because tablespace full\n",
table->name);
- row_drop_table_for_mysql(table->name, trx, TRUE);
+ row_drop_table_for_mysql(table->name, trx);
} else {
ut_a(err == DB_DUPLICATE_KEY);
@@ -1425,7 +1467,7 @@ row_create_index_for_mysql(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(index->table_name, trx, TRUE);
+ row_drop_table_for_mysql(index->table_name, trx);
trx->error_state = DB_SUCCESS;
}
@@ -1499,7 +1541,7 @@ row_table_add_foreign_constraints(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(name, trx, TRUE);
+ row_drop_table_for_mysql(name, trx);
trx->error_state = DB_SUCCESS;
}
@@ -1530,7 +1572,7 @@ row_drop_table_for_mysql_in_background(
name); */
/* Drop the table in InnoDB */
- error = row_drop_table_for_mysql(name, trx, FALSE);
+ error = row_drop_table_for_mysql(name, trx);
if (error != DB_SUCCESS) {
fprintf(stderr,
@@ -1689,9 +1731,7 @@ row_drop_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
- trx_t* trx, /* in: transaction handle */
- ibool has_dict_mutex) /* in: TRUE if the caller already owns the
- dictionary system mutex */
+ trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
que_thr_t* thr;
@@ -1703,6 +1743,7 @@ row_drop_table_for_mysql(
ulint namelen;
ulint keywordlen;
ulint rounds = 0;
+ ibool locked_dictionary = FALSE;
char buf[10000];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -1846,12 +1887,13 @@ row_drop_table_for_mysql(
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
- if (!has_dict_mutex) {
+ if (trx->dict_operation_lock_mode != RW_X_LATCH) {
/* Prevent foreign key checks etc. while we are dropping the
table */
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
+
+ locked_dictionary = TRUE;
}
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1948,9 +1990,8 @@ row_drop_table_for_mysql(
}
funct_exit:
- if (!has_dict_mutex) {
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&dict_operation_lock);
+ if (locked_dictionary) {
+ row_mysql_unlock_data_dictionary(trx);
}
que_graph_free(graph);
@@ -1986,8 +2027,7 @@ row_drop_database_for_mysql(
trx_start_if_not_started(trx);
loop:
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
while ((table_name = dict_get_first_table_name_in_db(name))) {
ut_a(memcmp(table_name, name, strlen(name)) == 0);
@@ -2000,8 +2040,7 @@ loop:
the table */
if (table->n_mysql_handles_opened > 0) {
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&dict_operation_lock);
+ row_mysql_unlock_data_dictionary(trx);
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -2016,7 +2055,7 @@ loop:
goto loop;
}
- err = row_drop_table_for_mysql(table_name, trx, TRUE);
+ err = row_drop_table_for_mysql(table_name, trx);
mem_free(table_name);
@@ -2028,8 +2067,7 @@ loop:
}
}
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&dict_operation_lock);
+ row_mysql_unlock_data_dictionary(trx);
trx_commit_for_mysql(trx);
@@ -2166,8 +2204,7 @@ row_rename_table_for_mysql(
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
table = dict_table_get_low(old_name);
@@ -2249,8 +2286,7 @@ row_rename_table_for_mysql(
}
}
funct_exit:
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&dict_operation_lock);
+ row_mysql_unlock_data_dictionary(trx);
que_graph_free(graph);
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index 3d9ae6aad8b..b64003f22d4 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -24,6 +24,7 @@ Created 3/14/1997 Heikki Tuuri
#include "row0row.h"
#include "row0upd.h"
#include "row0vers.h"
+#include "row0mysql.h"
#include "log0log.h"
/************************************************************************
@@ -454,8 +455,8 @@ ibool
row_purge_parse_undo_rec(
/*=====================*/
/* out: TRUE if purge operation required:
- NOTE that then the CALLER must s-unlock
- dict_operation_lock! */
+ NOTE that then the CALLER must unfreeze
+ data dictionary! */
purge_node_t* node, /* in: row undo node */
ibool* updated_extern,
/* out: TRUE if an externally stored field
@@ -464,6 +465,7 @@ row_purge_parse_undo_rec(
{
dict_index_t* clust_index;
byte* ptr;
+ trx_t* trx;
dulint undo_no;
dulint table_id;
dulint trx_id;
@@ -473,6 +475,8 @@ row_purge_parse_undo_rec(
ulint cmpl_info;
ut_ad(node && thr);
+
+ trx = thr_get_trx(thr);
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
updated_extern, &undo_no, &table_id);
@@ -498,17 +502,18 @@ row_purge_parse_undo_rec(
/* Prevent DROP TABLE etc. from running when we are doing the purge
for this row */
- rw_lock_s_lock(&dict_operation_lock);
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_freeze_data_dictionary(trx);
- node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
+ mutex_enter(&(dict_sys->mutex));
- mutex_exit(&(dict_sys->mutex));
+ node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
+ mutex_exit(&(dict_sys->mutex));
+
if (node->table == NULL) {
/* The table has been dropped: no need to do purge */
- rw_lock_s_unlock(&dict_operation_lock);
+ row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
@@ -518,7 +523,7 @@ row_purge_parse_undo_rec(
if (clust_index == NULL) {
/* The table was corrupt in the data dictionary */
- rw_lock_s_unlock(&dict_operation_lock);
+ row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
@@ -556,9 +561,12 @@ row_purge(
dulint roll_ptr;
ibool purge_needed;
ibool updated_extern;
+ trx_t* trx;
ut_ad(node && thr);
+ trx = thr_get_trx(thr);
+
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
&(node->reservation),
node->heap);
@@ -577,8 +585,8 @@ row_purge(
} else {
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
thr);
- /* If purge_needed == TRUE, we must also remember to unlock
- dict_operation_lock! */
+ /* If purge_needed == TRUE, we must also remember to unfreeze
+ data dictionary! */
}
if (purge_needed) {
@@ -600,7 +608,7 @@ row_purge(
btr_pcur_close(&(node->pcur));
}
- rw_lock_s_unlock(&dict_operation_lock);
+ row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c
index 6f1cfc4db9f..01b0b1ab41e 100644
--- a/innobase/row/row0undo.c
+++ b/innobase/row/row0undo.c
@@ -24,6 +24,7 @@ Created 1/8/1997 Heikki Tuuri
#include "row0row.h"
#include "row0uins.h"
#include "row0umod.h"
+#include "row0mysql.h"
#include "srv0srv.h"
/* How to undo row operations?
@@ -204,6 +205,7 @@ row_undo(
ulint err;
trx_t* trx;
dulint roll_ptr;
+ ibool froze_data_dict = FALSE;
ut_ad(node && thr);
@@ -256,13 +258,13 @@ row_undo(
/* Prevent DROP TABLE etc. while we are rolling back this row.
If we are doing a TABLE CREATE or some other dictionary operation,
then we already have dict_operation_lock locked in x-mode. Do not
- try to lock again in s-mode, because that would cause a hang.
-
- TODO: keep track when trx exactly has the latch locked!!!
- TODO: trx->dict_operation tells it only in some cases!!! */
-
- if (!trx->dict_operation) {
- rw_lock_s_lock(&dict_operation_lock);
+ try to lock again in s-mode, because that would cause a hang. */
+
+ if (trx->dict_operation_lock_mode == 0) {
+
+ row_mysql_freeze_data_dictionary(trx);
+
+ froze_data_dict = TRUE;
}
if (node->state == UNDO_NODE_INSERT) {
@@ -275,9 +277,9 @@ row_undo(
err = row_undo_mod(node, thr);
}
- if (!trx->dict_operation) {
+ if (froze_data_dict) {
- rw_lock_s_unlock(&dict_operation_lock);
+ row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 0be4f901d16..1231c94da63 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -89,14 +89,16 @@ row_upd_index_is_referenced(
{
dict_table_t* table = index->table;
dict_foreign_t* foreign;
+ ibool froze_data_dict = FALSE;
if (!UT_LIST_GET_FIRST(table->referenced_list)) {
return(FALSE);
}
- if (!trx->has_dict_operation_lock) {
- rw_lock_s_lock(&dict_operation_lock);
+ if (trx->dict_operation_lock_mode == 0) {
+ row_mysql_freeze_data_dictionary(trx);
+ froze_data_dict = TRUE;
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
@@ -104,8 +106,8 @@ row_upd_index_is_referenced(
while (foreign) {
if (foreign->referenced_index == index) {
- if (!trx->has_dict_operation_lock) {
- rw_lock_s_unlock(&dict_operation_lock);
+ if (froze_data_dict) {
+ row_mysql_unfreeze_data_dictionary(trx);
}
return(TRUE);
@@ -114,8 +116,8 @@ row_upd_index_is_referenced(
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
- if (!trx->has_dict_operation_lock) {
- rw_lock_s_unlock(&dict_operation_lock);
+ if (froze_data_dict) {
+ row_mysql_unfreeze_data_dictionary(trx);
}
return(FALSE);
@@ -162,12 +164,10 @@ row_upd_check_references_constraints(
mtr_start(mtr);
- if (!trx->has_dict_operation_lock) {
+ if (trx->dict_operation_lock_mode == 0) {
got_s_lock = TRUE;
- rw_lock_s_lock(&dict_operation_lock);
-
- trx->has_dict_operation_lock = TRUE;
+ row_mysql_freeze_data_dictionary(trx);
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
@@ -211,10 +211,7 @@ row_upd_check_references_constraints(
if (err != DB_SUCCESS) {
if (got_s_lock) {
- rw_lock_s_unlock(
- &dict_operation_lock);
- trx->has_dict_operation_lock
- = FALSE;
+ row_mysql_unfreeze_data_dictionary(trx);
}
mem_heap_free(heap);
@@ -227,8 +224,7 @@ row_upd_check_references_constraints(
}
if (got_s_lock) {
- rw_lock_s_unlock(&dict_operation_lock);
- trx->has_dict_operation_lock = FALSE;
+ row_mysql_unfreeze_data_dictionary(trx);
}
mem_heap_free(heap);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 11e45df4ce3..51d7878fd29 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -51,6 +51,10 @@ Created 10/8/1995 Heikki Tuuri
#include "srv0start.h"
#include "row0mysql.h"
+/* This is set to TRUE if the MySQL user has set it in MySQL; currently
+affects only FOREIGN KEY definition parsing */
+ibool srv_lower_case_table_names = FALSE;
+
/* Buffer which can be used in printing fatal error messages */
char srv_fatal_errbuf[5000];
@@ -2064,6 +2068,7 @@ srv_suspend_mysql_thread(
os_event_t event;
double wait_time;
trx_t* trx;
+ ibool had_dict_lock = FALSE;
ut_ad(!mutex_own(&kernel_mutex));
@@ -2107,18 +2112,22 @@ srv_suspend_mysql_thread(
srv_conc_force_exit_innodb(thr_get_trx(thr));
/* Release possible foreign key check latch */
- if (trx->has_dict_operation_lock) {
+ if (trx->dict_operation_lock_mode == RW_S_LATCH) {
+
+ had_dict_lock = TRUE;
- rw_lock_s_unlock(&dict_operation_lock);
+ row_mysql_unfreeze_data_dictionary(trx);
}
+ ut_a(trx->dict_operation_lock_mode == 0);
+
/* Wait for the release */
os_event_wait(event);
- if (trx->has_dict_operation_lock) {
+ if (had_dict_lock) {
- rw_lock_s_lock(&dict_operation_lock);
+ row_mysql_freeze_data_dictionary(trx);
}
/* Return back inside InnoDB */
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index cad946b1e54..d006b4ec915 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1380,7 +1380,7 @@ innobase_start_or_create_for_mysql(void)
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
fprintf(stderr,
"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n"
- "InnoDB: success! Cannot continue.\n");
+"InnoDB: success! Cannot continue.\n");
exit(1);
}
@@ -1390,11 +1390,17 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex);
- if (srv_print_verbose_log)
- {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Started\n");
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Started\n");
}
+
+ if (srv_force_recovery > 0) {
+ fprintf(stderr,
+ "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
+ srv_force_recovery);
+ }
+
return((int) DB_SUCCESS);
}
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 4c2ee5dc9be..1f0e0c58ac7 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -254,7 +254,7 @@ loop:
mutex_exit(&kernel_mutex);
if (trx->dict_operation) {
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
}
que_run_threads(thr);
@@ -290,14 +290,14 @@ loop:
fprintf(stderr,
"InnoDB: Table found: dropping table %s in recovery\n", table->name);
- err = row_drop_table_for_mysql(table->name, trx,
- TRUE);
+ err = row_drop_table_for_mysql(table->name, trx);
+
ut_a(err == (int) DB_SUCCESS);
}
}
if (trx->dict_operation) {
- mutex_exit(&(dict_sys->mutex));
+ row_mysql_unlock_data_dictionary(trx);
}
fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n",
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 7566fe1839e..9f711890f60 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -134,7 +134,7 @@ trx_create(
trx->lock_heap = mem_heap_create_in_buffer(256);
UT_LIST_INIT(trx->trx_locks);
- trx->has_dict_operation_lock = FALSE;
+ trx->dict_operation_lock_mode = 0;
trx->has_search_latch = FALSE;
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
@@ -261,6 +261,8 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
+ ut_a(trx->dict_operation_lock_mode == 0);
+
if (trx->lock_heap) {
mem_heap_free(trx->lock_heap);
}