Bug #57700 Latching order violation in row_truncate_table_for_mysql()
Submitted: 25 Oct 2010 0:48 Modified: 15 Dec 2010 0:44
Reporter: Sunny Bains Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:5.1+ OS:Any
Assigned to: Jimmy Yang CPU Architecture:Any
Tags: regression

[25 Oct 2010 0:48] Sunny Bains
Description:
The fix for bug# 54678 breaks the latching order. It acquires SYNC_INDEX_TREE(900)
before SYNC_DICT_HEADER(995) during truncate.

How to repeat:
Must have UNIV_SYNC_DEBUG set and  "if (table->space && !table->dir_path_of_temp_table) {"
this must evaluate to true in the test, in the reported function.

Suggested fix:
Avoid the latching order violation when generating the space id for a new table/index.
[25 Oct 2010 1:42] Jimmy Yang
As mentioned in the report, the assertion happens when a few conditions met, 1) UNIV_SYNC_DEBUG is set during compilation 2) table->space  is true, 3) !table->dir_path_of_temp_table.

The reason being the dict_hdr_get_new_id() call would lock dict header with a high priority latch than dict index. Fix is straight forward to move dict_table_x_lock_indexes() after dict_hdr_get_new_id():

-       /* Lock all index trees for this table, as we will
-       truncate the table/index and possibly change their metadata.
-       All DML/DDL are blocked by table level lock, with
-       a few exceptions such as queries into information schema
-       about the table, MySQL could try to access index stats
-       for this kind of query, we need to use index locks to
-       sync up */
-       dict_table_x_lock_indexes(table);
-
        if (table->space && !table->dir_path_of_temp_table) {
                /* Discard and create the single-table tablespace. */
                ulint   space   = table->space;
@@ -2855,6 +2846,11 @@

                        dict_hdr_get_new_id(NULL, NULL, &space);

+                       /* Lock all index trees for this table. We must
+                       do so after dict_hdr_get_new_id() to preserve
+                       the latch order */
+                       dict_table_x_lock_indexes(table);
+
                        if (space == ULINT_UNDEFINED
@@ -2888,8 +2884,18 @@
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
                        mtr_commit(&mtr);
                }
+       } else {
+               /* Lock all index trees for this table, as we will
+               truncate the table/index and possibly change their metadata.
+               All DML/DDL are blocked by table level lock, with
+               a few exceptions such as queries into information schema
+               about the table, MySQL could try to access index stats
+               for this kind of query, we need to use index locks to
+               sync up */
+               dict_table_x_lock_indexes(table);
        }
[25 Oct 2010 10:26] Davi Arnaut
>               All DML/DDL are blocked by table level lock, with
>               a few exceptions such as queries into information schema
>               about the table, MySQL could try to access index stats
>               for this kind of query, we need to use index locks to
>               sync up */

BTW, it might be worth to update this and the other comments in the function to reflect that now there is a exclusive metadata lock on the table.
[13 Nov 2010 16:15] Bugs System
Pushed into mysql-trunk 5.6.99-m5 (revid:alexander.nozdrin@oracle.com-20101113155825-czmva9kg4n31anmu) (version source revid:alexander.nozdrin@oracle.com-20101113152450-2zzcm50e7i4j35v7) (merge vers: 5.6.1-m4) (pib:21)
[13 Nov 2010 16:41] Bugs System
Pushed into mysql-next-mr (revid:alexander.nozdrin@oracle.com-20101113160336-atmtmfb3mzm4pz4i) (version source revid:alexander.nozdrin@oracle.com-20101113152540-gxro4g0v29l27f5x) (pib:21)
[18 Nov 2010 15:56] Bugs System
Pushed into mysql-5.1 5.1.54 (revid:build@mysql.com-20101118153531-693taxtxyxpt037i) (version source revid:build@mysql.com-20101118153531-693taxtxyxpt037i) (merge vers: 5.1.54) (pib:21)
[5 Dec 2010 12:43] Bugs System
Pushed into mysql-trunk 5.6.1 (revid:alexander.nozdrin@oracle.com-20101205122447-6x94l4fmslpbttxj) (version source revid:alexander.nozdrin@oracle.com-20101205122447-6x94l4fmslpbttxj) (merge vers: 5.6.1) (pib:23)
[15 Dec 2010 0:44] John Russell
Added to change log:

A followup fix to bug #54678. TRUNCATE TABLE could still could cause
a crash (assertion error) in the debug version of the server.
[16 Dec 2010 22:34] Bugs System
Pushed into mysql-5.5 5.5.9 (revid:jonathan.perkin@oracle.com-20101216101358-fyzr1epq95a3yett) (version source revid:jonathan.perkin@oracle.com-20101216101358-fyzr1epq95a3yett) (merge vers: 5.5.9) (pib:24)