Bug #55027 assertion: mutex_own(&dict_sys->mutex) in dict_table_get_on_id()

Submitted: 6 Jul 2010 13:32 Modified: 26 Oct 2010 21:45
Reporter: Mikhail Izioumtchenko Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:5.1 OS:Any
Assigned to: Sunny Bains CPU Architecture:Any

[6 Jul 2010 13:32] Mikhail Izioumtchenko
Description:
this is builtin only bug which started to happen after merging the fix
to bug#54583. It has a very good reproducibility with 5.1 builtin
but not with any version of the plugin with the same fix to bug#54583 present.
The stack backtrace would look like

 #5  0x0000003acbc31d10 in abort () from /lib64/libc.so.6
 #6  0x000000000080fe10 in dict_table_get_on_id (table_id=...,
     trx=0x2aaaac07f0b8) at dict/dict0dict.c:625
 #7  0x00000000008b5c3d in row_undo_mod_parse_undo_rec (node=0x2aaaac0868b8,
     thr=0x2aaaac06c1b0) at row/row0umod.c:672
 #8  0x00000000008b5e36 in row_undo_mod (node=0x2aaaac0868b8,
     thr=0x2aaaac06c1b0) at row/row0umod.c:721
 #9  0x000000000087b79b in row_undo (node=0x2aaaac0868b8, thr=0x2aaaac06c1b0)
     at row/row0undo.c:285
 #10 0x000000000087b892 in row_undo_step (thr=0x2aaaac06c1b0)
     at row/row0undo.c:327
 #11 0x000000000085de15 in que_thr_step (thr=0x2aaaac06c1b0)
     at que/que0que.c:1254
 #12 0x000000000085e017 in que_run_threads_low (thr=0x2aaaac06c1b0)
     at que/que0que.c:1319
 #13 0x000000000085e122 in que_run_threads (thr=0x2aaaac05fdb0)
     at que/que0que.c:1355
 #14 0x000000000089299b in trx_rollback_or_clean_all_without_sess (
     arg=0x7fff7d8ee38c) at trx/trx0roll.c:538

and the table is a system table, SYS_COULMNS iirc

How to repeat:
reproducibility looks good in my standard stress/recovery testing.

Suggested fix:
not sure. This seems to be the same assert that made Marko introduce
X dictionary locking in row_undo. Temporarily removing the fix to bug#54583
is one option.
[6 Jul 2010 16:07] Mikhail Izioumtchenko
the bug I meant was bug#54538, not bug#54583. The 5.1 commit message
wrongly mentioned 54583.
[7 Jul 2010 5:52] Sunny Bains
The bug exists in both the builtin and the plugin  introduced by the fix
for bug# 54538. What has been confirmed now is that rename table
does not play by the rules. It does not set the dict_operation flag in
the UNDO record. Subsequently during recovery it will croak on
the failing assertion.

The recommended way to proceed then is:

  1. Revert the fix for bug# 54538
  2. Fix the rename table bug -- the actual underlying problem
  3. Reapply the fix for bug# 54538

It is trivial to reproduce this bug using GDB, break at row_rename_table_for_mysql(),
let it execute the "RENAME_TABLE" SQL procedure then sync the log files to disk and
then kill the server. On restart it will fail on the assertion.

In the MySQL client type:

 CREATE TABLE T(C INT) ENGINE=INNODB;
 RENAME TABLE T TO T1;
[7 Jul 2010 6:16] Sunny Bains
The real fix should really be to get rid of this check in dict_table_get_on_id():

  if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0

I don't see why it is required, either the data dictionary is X locked or it
isn't is all that should matter. If the caller already owns the dict_mutex but
hasn't X locked the data dictionary then the caller should call the alternative
dict_table_get_on_id_low() function.
[14 Jul 2010 15:53] Mikhail Izioumtchenko
setting back to verified. Question that may arise:
1. Why don't we see the bug in the plugin? One possibility is that RENAME
would have a shorter codepath, or maybe it's already calling 
dict_table_get_on_id_low(). Or maybe even RENAME does set dict_operation
flag there
2. Shouldn't RENAME set that flag still, irrespective of what we do about
dict_table_get_on_id() calls? Plugin currently rolls back all dictionary
transaction first, then proceeds to other transactions, part of some fixes Marko implemented, so if RENAME
escapes it, it could create problems.
[15 Jul 2010 1:36] Sunny Bains
It is easily reproducible in the plugin too using GDB. One of my
previous comments mentions howto. Marko introduced the following
in the plugin:

/** Type of data dictionary operation */
typedef enum trx_dict_op {
        /** The transaction is not modifying the data dictionary. */
        TRX_DICT_OP_NONE = 0,
        /** The transaction is creating a table or an index, or
        dropping a table.  The table must be dropped in crash
        recovery.  This and TRX_DICT_OP_NONE are the only possible
        operation modes in crash recovery. */
        TRX_DICT_OP_TABLE = 1,
        /** The transaction is creating or dropping an index in an
        existing table.  In crash recovery, the data dictionary
        must be locked, but the table must not be dropped. */
        TRX_DICT_OP_INDEX = 2
} trx_dict_op_t;

It doesn't capture the case of rename table. It is essentially targeted at dropping
temporary tables and indexes only during startup.
[2 Aug 2010 12:42] Marko Mäkelä
True, I introduced TRX_DICT_OP_INDEX in the InnoDB Plugin 1.0, for the crash recovery of Fast Index Creation aka Smart ALTER TABLE. Before that, trx->dict_operation was a Boolean flag, which told InnoDB to drop the table during crash recovery, when rolling back an incomplete transaction that was executing CREATE TABLE or a table-copying DDL operation.

We should decide how to handle RENAME TABLE here. Possible fixes include relaxing the assertion or setting the dict_operation flag to an appropriate value.
[19 Aug 2010 11:59] Marko Mäkelä
OK to push the fix:

-       if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
-           || trx->dict_operation_lock_mode == RW_X_LATCH) {
+       if (trx->dict_operation_lock_mode == RW_X_LATCH) {
[28 Sep 2010 8:49] Bugs System
Pushed into mysql-5.1 5.1.52 (revid:sunanda.menon@sun.com-20100928083322-wangbv97uobu7g66) (version source revid:sunanda.menon@sun.com-20100928083322-wangbv97uobu7g66) (merge vers: 5.1.52) (pib:21)
[28 Sep 2010 15:40] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@sun.com-20100928153607-tdsxkdm5cmuym5sq) (version source revid:alik@sun.com-20100928153508-0saa6v93dinqx1u7) (merge vers: 5.6.1-m4) (pib:21)
[28 Sep 2010 15:43] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100928153646-pqp8o1a92mxtuj3h) (version source revid:alik@sun.com-20100928153532-lr3gtvnyp2en4y75) (pib:21)
[28 Sep 2010 15:45] Bugs System
Pushed into mysql-5.5 5.5.7-rc (revid:alik@sun.com-20100928153459-4nudf4zgzlou4s7q) (version source revid:alik@sun.com-20100928153459-4nudf4zgzlou4s7q) (merge vers: 5.5.7-rc) (pib:21)
[14 Oct 2010 8:29] Bugs System
Pushed into mysql-5.1-telco-7.0 5.1.51-ndb-7.0.20 (revid:martin.skold@mysql.com-20101014082627-jrmy9xbfbtrebw3c) (version source revid:martin.skold@mysql.com-20101014082627-jrmy9xbfbtrebw3c) (merge vers: 5.1.51-ndb-7.0.20) (pib:21)
[14 Oct 2010 8:44] Bugs System
Pushed into mysql-5.1-telco-6.3 5.1.51-ndb-6.3.39 (revid:martin.skold@mysql.com-20101014083757-5qo48b86d69zjvzj) (version source revid:martin.skold@mysql.com-20101014083757-5qo48b86d69zjvzj) (merge vers: 5.1.51-ndb-6.3.39) (pib:21)
[14 Oct 2010 8:59] Bugs System
Pushed into mysql-5.1-telco-6.2 5.1.51-ndb-6.2.19 (revid:martin.skold@mysql.com-20101014084420-y54ecj85j5we27oa) (version source revid:martin.skold@mysql.com-20101014084420-y54ecj85j5we27oa) (merge vers: 5.1.51-ndb-6.2.19) (pib:21)
[26 Oct 2010 21:45] John Russell
Added to change log:

If the server crashed during a RENAME TABLE operation on an InnoDB
table, subsequent crash recovery could fail. This problem could also
affect an ALTER TABLE statement that caused a rename operation
internally.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.050 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.