From: Jon Olav Hauglid Date: March 7 2011 9:08am Subject: bzr commit into mysql-5.5 branch (jon.hauglid:3374) Bug#11764779 List-Archive: http://lists.mysql.com/commits/132524 X-Bug: 11764779 Message-Id: <201103070908.p271xgeg025299@acsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3050797091803267465==" --===============3050797091803267465== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/x/mysql-5.5-bug57649/ based on revid:alexander.barkov@stripped 3374 Jon Olav Hauglid 2011-03-07 Bug #11764779 (former 57649) FLUSH TABLES under FLUSH TABLES WITH READ LOCK leads to assert failure. This assert was triggered if a statement tried up upgrade a metadata lock with an active FLUSH TABLE WITH READ LOCK. The assert checks that the connection already holds a global intention exclusive metadata lock. However, FLUSH TABLE WITH READ LOCK does not acquire this lock in order to be compatible with FLUSH TABLES WITH READ LOCK. Therefore any metadata lock upgrade caused the assert to be triggered. This patch fixes the problem by preventing metadata lock upgrade if the connection has an active FLUSH TABLE WITH READ LOCK. ER_TABLE_NOT_LOCKED_FOR_WRITE will instead be reported to the client. Test case added to flush.test. modified: mysql-test/r/flush.result mysql-test/t/flush.test sql/sql_base.cc sql/sql_base.h sql/sql_reload.cc sql/sql_table.cc sql/sql_trigger.cc sql/sql_truncate.cc === modified file 'mysql-test/r/flush.result' --- a/mysql-test/r/flush.result 2010-11-11 17:11:05 +0000 +++ b/mysql-test/r/flush.result 2011-03-07 09:08:10 +0000 @@ -451,3 +451,18 @@ unlock tables; handler t1 close; # Cleanup. drop tables t1, t2; +# +# Bug#57649 FLUSH TABLES under FLUSH TABLES WITH READ LOCK leads +# to assert failure. +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT); +FLUSH TABLES t1 WITH READ LOCK; +FLUSH TABLES; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a= 1; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +ALTER TABLE t1 COMMENT 'test'; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +UNLOCK TABLES; +DROP TABLE t1; === modified file 'mysql-test/t/flush.test' --- a/mysql-test/t/flush.test 2010-11-11 17:11:05 +0000 +++ b/mysql-test/t/flush.test 2011-03-07 09:08:10 +0000 @@ -644,3 +644,27 @@ disconnect con2; --source include/wait_until_disconnected.inc connection default; drop tables t1, t2; + + +--echo # +--echo # Bug#57649 FLUSH TABLES under FLUSH TABLES WITH READ LOCK leads +--echo # to assert failure. +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a INT); +FLUSH TABLES t1 WITH READ LOCK; + +# All these triggered the assertion +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +FLUSH TABLES; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a= 1; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +ALTER TABLE t1 COMMENT 'test'; + +UNLOCK TABLES; +DROP TABLE t1; === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2011-02-08 15:47:33 +0000 +++ b/sql/sql_base.cc 2011-03-07 09:08:10 +0000 @@ -1026,7 +1026,7 @@ bool close_cached_tables(THD *thd, TABLE table_list= table_list->next_global) { /* A check that the table was locked for write is done by the caller. */ - TABLE *table= find_table_for_mdl_upgrade(thd->open_tables, table_list->db, + TABLE *table= find_table_for_mdl_upgrade(thd, table_list->db, table_list->table_name, TRUE); /* May return NULL if this table has already been closed via an alias. */ @@ -3120,22 +3120,26 @@ TABLE *find_locked_table(TABLE *list, co lock from the list of open tables, emit error if no such table found. - @param list List of TABLE objects to be searched + @param thd Thread context @param db Database name. @param table_name Name of table. @param no_error Don't emit error if no suitable TABLE instance were found. + @note This function checks if the connection holds a global IX + metadata lock. If no such lock is found, it is not safe to + upgrade the lock and ER_TABLE_NOT_LOCKED_FOR_WRITE will be + reported. + @return Pointer to TABLE instance with MDL_SHARED_NO_WRITE, MDL_SHARED_NO_READ_WRITE, or MDL_EXCLUSIVE metadata lock, NULL otherwise. */ -TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db, - const char *table_name, - bool no_error) +TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, + const char *table_name, bool no_error) { - TABLE *tab= find_locked_table(list, db, table_name); + TABLE *tab= find_locked_table(thd->open_tables, db, table_name); if (!tab) { @@ -3143,19 +3147,29 @@ TABLE *find_table_for_mdl_upgrade(TABLE my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_name); return NULL; } - else + + /* + It is not safe to upgrade the metadata lock without a global IX lock. + This can happen with FLUSH TABLES WITH READ LOCK as we in these + cases don't take a global IX lock in order to be compatible with + global read lock. + */ + if (!thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", + MDL_INTENTION_EXCLUSIVE)) { - while (tab->mdl_ticket != NULL && - !tab->mdl_ticket->is_upgradable_or_exclusive() && - (tab= find_locked_table(tab->next, db, table_name))) - continue; - if (!tab) - { - if (!no_error) - my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name); - return 0; - } + if (!no_error) + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name); + return NULL; } + + while (tab->mdl_ticket != NULL && + !tab->mdl_ticket->is_upgradable_or_exclusive() && + (tab= find_locked_table(tab->next, db, table_name))) + continue; + + if (!tab && !no_error) + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name); + return tab; } @@ -4653,8 +4667,7 @@ open_tables_check_upgradable_mdl(THD *th Note that find_table_for_mdl_upgrade() will report an error if no suitable ticket is found. */ - if (!find_table_for_mdl_upgrade(thd->open_tables, table->db, - table->table_name, FALSE)) + if (!find_table_for_mdl_upgrade(thd, table->db, table->table_name, false)) return TRUE; } } === modified file 'sql/sql_base.h' --- a/sql/sql_base.h 2010-11-11 17:11:05 +0000 +++ b/sql/sql_base.h 2011-03-07 09:08:10 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +/* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -290,7 +290,7 @@ bool tdc_open_view(THD *thd, TABLE_LIST char *cache_key, uint cache_key_length, MEM_ROOT *mem_root, uint flags); void tdc_flush_unused_tables(); -TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db, +TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, const char *table_name, bool no_error); void mark_tmp_table_for_reuse(TABLE *table); === modified file 'sql/sql_reload.cc' --- a/sql/sql_reload.cc 2010-12-07 16:11:13 +0000 +++ b/sql/sql_reload.cc 2011-03-07 09:08:10 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -220,12 +220,26 @@ bool reload_acl_and_cache(THD *thd, unsi if (tables) { for (TABLE_LIST *t= tables; t; t= t->next_local) - if (!find_table_for_mdl_upgrade(thd->open_tables, t->db, - t->table_name, FALSE)) + if (!find_table_for_mdl_upgrade(thd, t->db, t->table_name, false)) return 1; } else { + /* + It is not safe to upgrade the metadata lock without GLOBAL IX lock. + This can happen with FLUSH TABLES WITH READ LOCK as we in these + cases don't take a GLOBAL IX lock in order to be compatible with + global read lock. + */ + if (thd->open_tables && + !thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", + MDL_INTENTION_EXCLUSIVE)) + { + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), + thd->open_tables->s->table_name.str); + return true; + } + for (TABLE *tab= thd->open_tables; tab; tab= tab->next) { if (! tab->mdl_ticket->is_upgradable_or_exclusive()) === modified file 'sql/sql_table.cc' --- a/sql/sql_table.cc 2011-01-26 13:23:29 +0000 +++ b/sql/sql_table.cc 2011-03-07 09:08:10 +0000 @@ -1917,7 +1917,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST by parser) it is safe to cache pointer to the TABLE instances in its elements. */ - table->table= find_table_for_mdl_upgrade(thd->open_tables, table->db, + table->table= find_table_for_mdl_upgrade(thd, table->db, table->table_name, false); if (!table->table) DBUG_RETURN(true); === modified file 'sql/sql_trigger.cc' --- a/sql/sql_trigger.cc 2010-11-11 17:11:05 +0000 +++ b/sql/sql_trigger.cc 2011-03-07 09:08:10 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2005 MySQL AB, 2008-2009 Sun Microsystems, Inc +/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -467,8 +467,7 @@ bool mysql_create_or_drop_trigger(THD *t if (thd->locked_tables_mode) { /* Under LOCK TABLES we must only accept write locked tables. */ - if (!(tables->table= find_table_for_mdl_upgrade(thd->open_tables, - tables->db, + if (!(tables->table= find_table_for_mdl_upgrade(thd, tables->db, tables->table_name, FALSE))) goto end; === modified file 'sql/sql_truncate.cc' --- a/sql/sql_truncate.cc 2010-10-29 14:10:53 +0000 +++ b/sql/sql_truncate.cc 2011-03-07 09:08:10 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -327,7 +327,7 @@ bool Truncate_statement::lock_table(THD */ if (thd->locked_tables_mode) { - if (!(table= find_table_for_mdl_upgrade(thd->open_tables, table_ref->db, + if (!(table= find_table_for_mdl_upgrade(thd, table_ref->db, table_ref->table_name, FALSE))) DBUG_RETURN(TRUE); --===============3050797091803267465== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/jon.hauglid@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: jon.hauglid@stripped # target_branch: file:///export/home/x/mysql-5.5-bug57649/ # testament_sha1: 93ab0c5b8b82f4b900920f13f75e82c238cc8935 # timestamp: 2011-03-07 10:08:13 +0100 # base_revision_id: alexander.barkov@stripped\ # 95d3bhwhda84fyjc # # Begin bundle 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 w6zEM0GukEUq4fP6D/8XckU4UJB9ZYbx --===============3050797091803267465==--