summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunny Bains <Sunny.Bains@Oracle.Com>2010-06-25 18:18:41 +1000
committerSunny Bains <Sunny.Bains@Oracle.Com>2010-06-25 18:18:41 +1000
commit7299858763289eab8c9fbe8048f86abebdf4d50d (patch)
treeb7d388c25f663205992626dc6754807c1c02c2db
parentdec092962b83aaf37ce2c36e6d8287987046d46f (diff)
downloadmariadb-git-7299858763289eab8c9fbe8048f86abebdf4d50d.tar.gz
Fix bug#54583. This change reverses rsvn:1350 by getting rid of a bogus assertion
and clarifies the invariant in dict_table_get_on_id(). In Mar 2007 Marko observed a crash during recovery, the crash resulted from an UNDO operation on a system table. His solution was to acquire an X lock on the data dictionary, this in hindsight was an overkill. It is unclear what caused the crash, current hypothesis is that it was a memory corruption. The X lock results in performance issues by when undoing changes due to rollback during normal operation on regular tables. Why the change is safe: ====================== The InnoDB code has changed since the original X lock change was made. In the new code we always lock the data dictionary in X mode during startup when UNDOing operations on the system tables (this is a given). This ensures that the crash Marko observed cannot happen as long as all transactions that update the system tables follow the standard rules by setting the appropriate DICT_OP flag when writing the log records when they make the changes. If transactions violate the above mentioned rule then during recovery (at startup) the rollback code (see trx0roll.c) will not acquire the X lock and we will see the crash again. This will however be a different bug.
-rw-r--r--storage/innobase/dict/dict0dict.c10
-rw-r--r--storage/innobase/include/sync0sync.h2
-rw-r--r--storage/innobase/row/row0undo.c4
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c10
-rw-r--r--storage/innodb_plugin/include/sync0sync.h2
-rw-r--r--storage/innodb_plugin/row/row0undo.c4
6 files changed, 14 insertions, 18 deletions
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index d3b277d2d7a..d2b59469cdc 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -618,13 +618,11 @@ dict_table_get_on_id(
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
- /* It is a system table which will always exist in the table
- cache: we avoid acquiring the dictionary mutex, because
- if we are doing a rollback to handle an error in TABLE
- CREATE, for example, we already have the mutex! */
- ut_ad(mutex_own(&(dict_sys->mutex))
- || trx->dict_operation_lock_mode == RW_X_LATCH);
+ /* Note: An X latch implies that the transaction
+ already owns the dictionary mutex. */
+
+ ut_ad(mutex_own(&dict_sys->mutex));
return(dict_table_get_on_id_low(table_id));
}
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index 6a61330f97e..9430d4cb723 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -401,7 +401,7 @@ or row lock! */
locked; see e.g.
ibuf_bitmap_get_map_page(). */
#define SYNC_DICT_OPERATION 1001 /* 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 */
#define SYNC_DICT 1000
diff --git a/storage/innobase/row/row0undo.c b/storage/innobase/row/row0undo.c
index f03f84ed1b0..7f31fd0060c 100644
--- a/storage/innobase/row/row0undo.c
+++ b/storage/innobase/row/row0undo.c
@@ -272,7 +272,7 @@ row_undo(
if (locked_data_dict) {
- row_mysql_lock_data_dictionary(trx);
+ row_mysql_freeze_data_dictionary(trx);
}
if (node->state == UNDO_NODE_INSERT) {
@@ -287,7 +287,7 @@ row_undo(
if (locked_data_dict) {
- row_mysql_unlock_data_dictionary(trx);
+ row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index 8be5b7acac5..fe4e058e122 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -570,13 +570,11 @@ dict_table_get_on_id(
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
- /* It is a system table which will always exist in the table
- cache: we avoid acquiring the dictionary mutex, because
- if we are doing a rollback to handle an error in TABLE
- CREATE, for example, we already have the mutex! */
- ut_ad(mutex_own(&(dict_sys->mutex))
- || trx->dict_operation_lock_mode == RW_X_LATCH);
+ /* Note: An X latch implies that the transaction
+ already owns the dictionary mutex. */
+
+ ut_ad(mutex_own(&dict_sys->mutex));
return(dict_table_get_on_id_low(table_id));
}
diff --git a/storage/innodb_plugin/include/sync0sync.h b/storage/innodb_plugin/include/sync0sync.h
index d470b823fc3..71c9920a10b 100644
--- a/storage/innodb_plugin/include/sync0sync.h
+++ b/storage/innodb_plugin/include/sync0sync.h
@@ -438,7 +438,7 @@ or row lock! */
#define SYNC_FILE_FORMAT_TAG 1200 /* Used to serialize access to the
file format tag */
#define SYNC_DICT_OPERATION 1001 /* 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 */
#define SYNC_DICT 1000
diff --git a/storage/innodb_plugin/row/row0undo.c b/storage/innodb_plugin/row/row0undo.c
index 3d739c9689a..9ef842b5114 100644
--- a/storage/innodb_plugin/row/row0undo.c
+++ b/storage/innodb_plugin/row/row0undo.c
@@ -297,7 +297,7 @@ row_undo(
if (locked_data_dict) {
- row_mysql_lock_data_dictionary(trx);
+ row_mysql_freeze_data_dictionary(trx);
}
if (node->state == UNDO_NODE_INSERT) {
@@ -312,7 +312,7 @@ row_undo(
if (locked_data_dict) {
- row_mysql_unlock_data_dictionary(trx);
+ row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */