From 7955bd43f271f1b3035c6b09f7b2ec0a2d3c4651 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 16 Mar 2010 21:34:03 -0300 Subject: [PATCH 1/8] Fix assorted compiler warnings. sql/handler.cc: Initialize the "comment" member of the structure. sql/sql_base.cc: Compile out unused function. sql/sql_update.cc: Remove unused variable. sql/sys_vars.cc: Use correct format specifier. --- sql/handler.cc | 3 ++- sql/sql_base.cc | 2 ++ sql/sql_update.cc | 2 -- sql/sys_vars.cc | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 69ac4e72555..8431f610d46 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -46,7 +46,8 @@ static handlerton *installed_htons[128]; #define BITMAP_STACKBUF_SIZE (128/8) -KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} }; +KEY_CREATE_INFO default_key_create_info= + { HA_KEY_ALG_UNDEF, 0, {NullS, 0}, {NullS, 0} }; /* number of entries in handlertons[] */ ulong total_ha= 0; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a85a863abd9..fdcb215729c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -729,6 +729,7 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) } +#ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL /** @brief Mark table share as having one more user (increase its reference count). @@ -746,6 +747,7 @@ static void reference_table_share(TABLE_SHARE *share) (ulong) share, share->ref_count)); DBUG_VOID_RETURN; } +#endif /* diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 62a35335374..1fac036876d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -206,7 +206,6 @@ int mysql_update(THD *thd, ulonglong id; List all_fields; THD::killed_state killed_status= THD::NOT_KILLED; - MDL_ticket *start_of_statement_svp= thd->mdl_context.mdl_savepoint(); DBUG_ENTER("mysql_update"); if (open_tables(thd, &table_list, &table_count, 0)) @@ -956,7 +955,6 @@ int mysql_multi_update_prepare(THD *thd) uint table_count= lex->table_count; const bool using_lock_tables= thd->locked_tables_mode != LTM_NONE; bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI); - MDL_ticket *start_of_statement_svp= thd->mdl_context.mdl_savepoint(); DBUG_ENTER("mysql_multi_update_prepare"); /* following need for prepared statements, to run next time multi-update */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e14286210b4..fe0151a1847 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2803,7 +2803,7 @@ static Sys_var_charptr Sys_slave_load_tmpdir( static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type) { mysql_mutex_lock(&LOCK_active_mi); - DBUG_PRINT("info", ("slave_net_timeout=%lu mi->heartbeat_period=%.3f", + DBUG_PRINT("info", ("slave_net_timeout=%u mi->heartbeat_period=%.3f", slave_net_timeout, (active_mi? active_mi->heartbeat_period : 0.0))); if (active_mi && slave_net_timeout < active_mi->heartbeat_period) From 34c6fa6db8e04ed56f207803b09d889aea71ddab Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 16 Mar 2010 21:38:13 -0300 Subject: [PATCH 2/8] Rename tree. --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 4eab3d239d0..be5e1c348fa 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-trunk-bugfixing" +tree_name = "mysql-trunk-runtime" From 3ff33e5dc582a2966cd6d337fb18a78c1ae0aabc Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Wed, 14 Apr 2010 09:30:57 +0200 Subject: [PATCH 3/8] Bug #52367 Deadlock involving SET GLOBAL EVENT_SCHEDULER = OFF during rqg_mdl_deadlock test The problem was that if two connection threads simultaneously tries to execute "SET GLOBAL EVENT_SCHEDULER = OFF", one of them could hang waiting for the scheduler to stop. The first connection thread would kill the event scheduler thread and then start waiting for it to exit. The second connection thread would then find the event scheduler thread in the process of exiting and also wait for it to exit. However, since the event scheduler thread used signal to wake only one waiting thread, the other connection thread would be left waiting. This bug was a regression introduced by the fix for Bug#51160. Before #51160 it was not possible for two connection threads to try to stop the event scheduler thread simultaneously. This patch fixes the problem my making sure the event scheduler thread uses broadcast to notify all waiters that it is exiting. No test case added as this would require adding debug sync points to parts of the code where sync points are currently not used. The patch has been tested with the non-deterministic test case from the bug description as well as using the RQG. --- sql/event_scheduler.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 3ceb1597a41..d189a49d482 100755 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc +/* Copyright (C) 2004, 2010 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 @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mysql_priv.h" #include "events.h" @@ -497,8 +497,8 @@ Event_scheduler::run(THD *thd) deinit_event_thread(thd); scheduler_thd= NULL; state= INITIALIZED; - DBUG_PRINT("info", ("Signalling back to the stopper COND_state")); - mysql_cond_signal(&COND_state); + DBUG_PRINT("info", ("Broadcasting COND_state back to the stoppers")); + mysql_cond_broadcast(&COND_state); UNLOCK_DATA(); DBUG_RETURN(res); From d3d459a72c8a1b2f972560a77e2296db14df4a84 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Wed, 14 Apr 2010 09:40:45 +0200 Subject: [PATCH 4/8] Bug #52593 SHOW CREATE TABLE is blocked if table is locked for write by another connection The problem was that if a table was locked in one connection by LOCK TABLES ... WRITE, REPAIR TABLE or OPTIMIZE TABLE, SHOW CREATE TABLE from another connection would be blocked. As SHOW CREATE TABLE only reads metadata about the table, such blocking is not needed. The problem was that when SHOW CREATE TABLE tried to get a metadata lock on the table in order to open it, it used the wrong type of metadata lock request. It used MDL_SHARED_READ which is used when the intent is to read both table metadata and table data. Instead it should have used MDL_SHARED_HIGH_PRIO which signifies an intent to only read metadata. This patch fixes the problem by making sure SHOW CREATE TABLE uses the MDL_SHARED_HIGH_PRIO metadata lock request type when trying to open the table. The patch also fixes a similar problem with the mysql_list_fields API call. Test case added to show_check.test. --- mysql-test/r/show_check.result | 17 +++++++++++++++++ mysql-test/t/show_check.test | 26 ++++++++++++++++++++++++++ sql/sql_show.cc | 11 +++++++---- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index b6207d830d8..9ba1a0446dd 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1448,3 +1448,20 @@ DROP USER test_u@localhost; SHOW CREATE TABLE non_existent; ERROR 70100: Query execution was interrupted End of 5.1 tests +# +# Bug#52593 SHOW CREATE TABLE is blocked if table is locked +# for write by another connection +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT PRIMARY KEY); +LOCK TABLE t1 WRITE; +# Switching to connection 'con1'. +# This statement used to be blocked. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +# Switching to connection 'default'. +UNLOCK TABLES; +DROP TABLE t1; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 4f98b8b5128..ce75d02a1cc 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1212,6 +1212,32 @@ DISCONNECT con1; --echo End of 5.1 tests + +--echo # +--echo # Bug#52593 SHOW CREATE TABLE is blocked if table is locked +--echo # for write by another connection + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +connect(con1, localhost,root); +connection default; + +CREATE TABLE t1 (i INT PRIMARY KEY); +LOCK TABLE t1 WRITE; +--echo # Switching to connection 'con1'. +connection con1; +--echo # This statement used to be blocked. +SHOW CREATE TABLE t1; + +--echo # Switching to connection 'default'. +connection default; +disconnect con1; +UNLOCK TABLES; +DROP TABLE t1; + + # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 542a0378bf4..7e1ed8aec9e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +/* Copyright 2000, 2010 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 @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Function with list databases, tables or fields */ @@ -641,7 +641,9 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) { Show_create_error_handler view_error_suppressor(thd, table_list); thd->push_internal_handler(&view_error_suppressor); - bool error= open_normal_and_derived_tables(thd, table_list, 0); + bool error= + open_normal_and_derived_tables(thd, table_list, + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL); thd->pop_internal_handler(); if (error && (thd->killed || thd->is_error())) DBUG_RETURN(TRUE); @@ -815,7 +817,8 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) DBUG_ENTER("mysqld_list_fields"); DBUG_PRINT("enter",("table: %s",table_list->table_name)); - if (open_normal_and_derived_tables(thd, table_list, 0)) + if (open_normal_and_derived_tables(thd, table_list, + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL)) DBUG_VOID_RETURN; table= table_list->table; From 48ac4ff51f7391d4dd0826e0adebda2e24bc3feb Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Thu, 15 Apr 2010 09:16:29 +0200 Subject: [PATCH 5/8] Bug #51327 MyISAM table is automatically repaired on ALTER even if myisam-recover is OFF The problem was that a corrupted MyISAM table was auto repaired even if the myisam_recover_options server variable (or the myisam_recover option) was set to OFF. The reason was that the auto_repair() function, which is supposed to say if auto repair is to be used, did not use the server variable setting correctly. This bug was a regression introduced by WL#4738. This patch fixes the problem by making sure auto_repair() returns FALSE if myisam_recover_options is set to OFF. Test case added to myisam.test. --- mysql-test/r/myisam.result | 33 +++++++++++++++++++++++++++++++++ mysql-test/t/myisam.test | 31 +++++++++++++++++++++++++++++++ storage/myisam/ha_myisam.h | 6 +++--- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index df53b1d1480..73cf5df0304 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2342,3 +2342,36 @@ Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; End of 5.1 tests +# +# Bug#51327 MyISAM table is automatically repaired on ALTER +# even if myisam-recover is OFF +# +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table"); +call mtr.add_suppression(" '\..test.t1'"); +# Test that we can exchange a crashed partition with a table +SELECT @@global.myisam_recover_options; +@@global.myisam_recover_options +OFF +CREATE TABLE t1 (a INT, KEY (a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2); +FLUSH TABLES; +# replacing t.MYI with a corrupt + unclosed one created by doing: +# 'create table t1 (a int key(a))' head -c1024 t1.MYI > corrupt_t1.MYI +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check warning 1 client is using or hasn't closed the table properly +test.t1 check error Size of indexfile is: 1024 Should be: 2048 +test.t1 check warning Size of datafile is: 14 Should be: 7 +test.t1 check error Corrupt +# Alter table should report error and not auto-repair the table. +ALTER TABLE t1 ENGINE = MyISAM; +ERROR HY000: Table 't1' is marked as crashed and should be repaired +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check warning Table is marked as crashed +test.t1 check warning 1 client is using or hasn't closed the table properly +test.t1 check error Size of indexfile is: 1024 Should be: 2048 +test.t1 check warning Size of datafile is: 14 Should be: 7 +test.t1 check error Corrupt +DROP TABLE t1; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 47f53cac9ee..6c3092b22b8 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1591,3 +1591,34 @@ DROP TABLE t1; --echo End of 5.1 tests + +--echo # +--echo # Bug#51327 MyISAM table is automatically repaired on ALTER +--echo # even if myisam-recover is OFF +--echo # + +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table"); +call mtr.add_suppression(" '\..test.t1'"); + +let $MYSQLD_DATADIR = `SELECT @@datadir`; +--echo # Test that we can exchange a crashed partition with a table +SELECT @@global.myisam_recover_options; +CREATE TABLE t1 (a INT, KEY (a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2); +FLUSH TABLES; + +--echo # replacing t.MYI with a corrupt + unclosed one created by doing: +--echo # 'create table t1 (a int key(a))' head -c1024 t1.MYI > corrupt_t1.MYI +--remove_file $MYSQLD_DATADIR/test/t1.MYI +--copy_file std_data/corrupt_t1.MYI $MYSQLD_DATADIR/test/t1.MYI + +CHECK TABLE t1; +--echo # Alter table should report error and not auto-repair the table. +# Remove the path to t1 to prevent platform differences +--replace_regex /'[^']+'/'t1'/ +--error 145 +ALTER TABLE t1 ENGINE = MyISAM; +CHECK TABLE t1; + +DROP TABLE t1; diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 2f41670b934..71865d87fe2 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000, 2010 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 @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef USE_PRAGMA_INTERFACE @@ -124,7 +124,7 @@ class ha_myisam: public handler int repair(THD* thd, HA_CHECK_OPT* check_opt); bool check_and_repair(THD *thd); bool is_crashed() const; - bool auto_repair() const { return myisam_recover_options != 0; } + bool auto_repair() const { return myisam_recover_options != HA_RECOVER_OFF; } int optimize(THD* thd, HA_CHECK_OPT* check_opt); int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt); int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); From 4347e302a8f3410cecb159c1d90ac6bb00f00d1c Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Thu, 15 Apr 2010 14:14:28 +0200 Subject: [PATCH 6/8] Bug #51391 Deadlock involving events during rqg_info_schema test This was a deadlock between CREATE/ALTER/DROP EVENT and a query accessing both the mysql.event table and I_S.GLOBAL_VARIABLES. The root of the problem was that the LOCK_event_metadata mutex was used to both protect the "event_scheduler" global system variable and the internal event data structures used by CREATE/ALTER/DROP EVENT. The deadlock would occur if CREATE/ALTER/DROP EVENT held LOCK_event_metadata while trying to open the mysql.event table, at the same time as the query had mysql.event open, trying to lock LOCK_event_metadata to access "event_scheduler". This bug was fixed in the scope of Bug#51160 by using only LOCK_global_system_variables to protect "event_scheduler". This makes it so that the query above won't lock LOCK_event_metadata, thereby preventing this deadlock from occuring. This patch contains no code changes. Test case added to lock_sync.test. --- mysql-test/r/lock_sync.result | 20 ++++++++++++++++++++ mysql-test/t/lock_sync.test | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/mysql-test/r/lock_sync.result b/mysql-test/r/lock_sync.result index 49ef3bb1b37..18f3f6bc1a7 100644 --- a/mysql-test/r/lock_sync.result +++ b/mysql-test/r/lock_sync.result @@ -92,3 +92,23 @@ COMMIT; # Connection default # Reaping ALTER TABLE t1 ADD COLUMN j INT DROP TABLE t1, t2; +# +# Bug#51391 Deadlock involving events during rqg_info_schema test +# +CREATE EVENT e1 ON SCHEDULE EVERY 5 HOUR DO SELECT 1; +CREATE EVENT e2 ON SCHEDULE EVERY 5 HOUR DO SELECT 2; +# Connection con1 +SET DEBUG_SYNC="before_lock_tables_takes_lock SIGNAL drop WAIT_FOR query"; +# Sending: +DROP EVENT e1;; +# Connection default +SET DEBUG_SYNC="now WAIT_FOR drop"; +SELECT name FROM mysql.event, INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE definer = VARIABLE_VALUE; +name +SET DEBUG_SYNC="now SIGNAL query"; +# Connection con1 +# Reaping: DROP EVENT t1 +# Connection default +DROP EVENT e2; +SET DEBUG_SYNC="RESET"; diff --git a/mysql-test/t/lock_sync.test b/mysql-test/t/lock_sync.test index 97388e9c176..31884c1b79c 100644 --- a/mysql-test/t/lock_sync.test +++ b/mysql-test/t/lock_sync.test @@ -178,6 +178,39 @@ DROP TABLE t1, t2; disconnect con2; +--echo # +--echo # Bug#51391 Deadlock involving events during rqg_info_schema test +--echo # + +CREATE EVENT e1 ON SCHEDULE EVERY 5 HOUR DO SELECT 1; +CREATE EVENT e2 ON SCHEDULE EVERY 5 HOUR DO SELECT 2; + +--echo # Connection con1 +connect(con1, localhost, root); +SET DEBUG_SYNC="before_lock_tables_takes_lock SIGNAL drop WAIT_FOR query"; +--echo # Sending: +--send DROP EVENT e1; + +--echo # Connection default +connection default; +SET DEBUG_SYNC="now WAIT_FOR drop"; +SELECT name FROM mysql.event, INFORMATION_SCHEMA.GLOBAL_VARIABLES + WHERE definer = VARIABLE_VALUE; +SET DEBUG_SYNC="now SIGNAL query"; + +--echo # Connection con1 +connection con1; +--echo # Reaping: DROP EVENT t1 +--reap +disconnect con1; +--source include/wait_until_disconnected.inc + +--echo # Connection default +connection default; +DROP EVENT e2; +SET DEBUG_SYNC="RESET"; + + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc From cf8df9ca442200d9ea01d4480cb7bf70675ca188 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Thu, 15 Apr 2010 18:53:57 +0200 Subject: [PATCH 7/8] Bug #47459 Assertion in Diagnostics_area::set_eof_status on OPTIMIZE TABLE This assertion could be triggered during execution of OPTIMIZE TABLE for InnoDB tables. As part of optimize for InnoDB tables, the table is recreated and then opened again. If the reopen failed for any reason, the assertion would be triggered. This could for example be caused by a concurrent DROP TABLE executed by a different connection. The reason for the assertion was that any failures during reopening were ignored. This patch fixes the problem by making sure that the result of reopening the table is checked and that any error messages are sent to the client. Test case added to innodb_mysql_sync.test. --- mysql-test/r/innodb_mysql_sync.result | 24 +++++++++++++++++ mysql-test/t/innodb_mysql_sync.test | 37 +++++++++++++++++++++++++++ sql/sql_table.cc | 16 ++++++++---- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/innodb_mysql_sync.result b/mysql-test/r/innodb_mysql_sync.result index 039d8b74c07..0e75e62b13a 100644 --- a/mysql-test/r/innodb_mysql_sync.result +++ b/mysql-test/r/innodb_mysql_sync.result @@ -24,3 +24,27 @@ Warnings: Error 1030 Got error -1 from storage engine DROP TABLE t1; SET DEBUG_SYNC='RESET'; +# +# Bug#47459 Assertion in Diagnostics_area::set_eof_status on +# OPTIMIZE TABLE +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(a INT) ENGINE= InnoDB; +# Connection con1 +SET DEBUG_SYNC= "ha_admin_open_ltable SIGNAL opening WAIT_FOR dropped"; +# Sending: +OPTIMIZE TABLE t1; +# Connection default +SET DEBUG_SYNC= "now WAIT_FOR opening"; +DROP TABLE t1; +SET DEBUG_SYNC= "now SIGNAL dropped"; +# Connection con1 +# Reaping: OPTIMIZE TABLE t1 +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize error Table 'test.t1' doesn't exist +test.t1 optimize status Operation failed +Warnings: +Error 1146 Table 'test.t1' doesn't exist +# Connection default +SET DEBUG_SYNC= "RESET"; diff --git a/mysql-test/t/innodb_mysql_sync.test b/mysql-test/t/innodb_mysql_sync.test index 3f061e30293..ee92ee9f52e 100644 --- a/mysql-test/t/innodb_mysql_sync.test +++ b/mysql-test/t/innodb_mysql_sync.test @@ -43,6 +43,43 @@ DROP TABLE t1; SET DEBUG_SYNC='RESET'; +--echo # +--echo # Bug#47459 Assertion in Diagnostics_area::set_eof_status on +--echo # OPTIMIZE TABLE +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +connect (con1, localhost, root); +connection default; + +CREATE TABLE t1(a INT) ENGINE= InnoDB; + +--echo # Connection con1 +connection con1; +SET DEBUG_SYNC= "ha_admin_open_ltable SIGNAL opening WAIT_FOR dropped"; +--echo # Sending: +--send OPTIMIZE TABLE t1 + +--echo # Connection default +connection default; +SET DEBUG_SYNC= "now WAIT_FOR opening"; +DROP TABLE t1; +SET DEBUG_SYNC= "now SIGNAL dropped"; + +--echo # Connection con1 +connection con1; +--echo # Reaping: OPTIMIZE TABLE t1 +--reap + +--echo # Connection default +connection default; +disconnect con1; +SET DEBUG_SYNC= "RESET"; + + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2a9e01daf18..5b957cccabd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5016,11 +5016,17 @@ send_result_message: { /* Clear the ticket released in close_thread_tables(). */ table->mdl_request.ticket= NULL; - if ((table->table= open_ltable(thd, table, lock_type, 0)) && - ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0)) - result_code= 0; // analyze went ok - if (result_code) // analyze failed - table->table->file->print_error(result_code, MYF(0)); + DEBUG_SYNC(thd, "ha_admin_open_ltable"); + if (table->table= open_ltable(thd, table, lock_type, 0)) + { + result_code= table->table->file->ha_analyze(thd, check_opt); + if (result_code == HA_ADMIN_ALREADY_DONE) + result_code= HA_ADMIN_OK; + else if (result_code) // analyze failed + table->table->file->print_error(result_code, MYF(0)); + } + else + result_code= -1; // open failed } /* Start a new row for the final status row */ protocol->prepare_for_resend(); From afdf0f030c342e28c5cfd7220e55830b18424de3 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Mon, 19 Apr 2010 15:35:13 +0200 Subject: [PATCH 8/8] Additional test coverage for Bug#30977 Concurrent statement using stored function and DROP FUNCTION breaks SBR Bug#48246 assert in close_thread_table --- mysql-test/r/sp-lock.result | 42 +++++++++ mysql-test/r/sp_sync.result | 107 ++++++++++++++++++---- mysql-test/t/disabled.def | 1 - mysql-test/t/sp-lock.test | 62 +++++++++++++ mysql-test/t/sp_sync.test | 174 ++++++++++++++++++++++++++++-------- sql/sql_parse.cc | 6 ++ 6 files changed, 337 insertions(+), 55 deletions(-) diff --git a/mysql-test/r/sp-lock.result b/mysql-test/r/sp-lock.result index e9087f61807..a7823175b3c 100644 --- a/mysql-test/r/sp-lock.result +++ b/mysql-test/r/sp-lock.result @@ -693,5 +693,47 @@ set @@session.max_sp_recursion_depth=default; # --> connection con3 # --> connection default # +# SHOW CREATE PROCEDURE p1 called from p1, after p1 was altered +# +# We are just covering the existing behaviour with tests. The +# results are not necessarily correct." +# +CREATE PROCEDURE p1() +BEGIN +SELECT get_lock("test", 10); +SHOW CREATE PROCEDURE p1; +END| +# Connection default +SELECT get_lock("test", 10); +get_lock("test", 10) +1 +# Connection 2 +# Will halt before executing SHOW CREATE PROCEDURE p1 +# Sending: +CALL p1(); +# Connection 3 +# Alter p1 +DROP PROCEDURE p1; +CREATE PROCEDURE p1() BEGIN END; +# Connection default +# Resume CALL p1, now with new p1 +SELECT release_lock("test"); +release_lock("test") +1 +# Connection 2 +# Reaping: CALL p1() +get_lock("test", 10) +1 +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +BEGIN +SELECT get_lock("test", 10); +SHOW CREATE PROCEDURE p1; +END latin1 latin1_swedish_ci latin1_swedish_ci +# Connection 3 +# Connection 2 +# Connection default; +DROP PROCEDURE p1; +# # End of 5.5 tests # diff --git a/mysql-test/r/sp_sync.result b/mysql-test/r/sp_sync.result index afa37e70531..a16babaef67 100644 --- a/mysql-test/r/sp_sync.result +++ b/mysql-test/r/sp_sync.result @@ -1,23 +1,94 @@ Tests of syncronization of stored procedure execution. +SET DEBUG_SYNC= 'RESET'; # -# Bug#48157: crash in Item_field::used_tables +# Bug #30977 Concurrent statement using stored function and +# DROP FUNCTION breaks SBR # -CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; -CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; -CREATE PROCEDURE p1() -BEGIN -UPDATE t1 JOIN t2 USING( a, b ) SET t1.b = 1, t2.b = 1; -END| -LOCK TABLES t1 WRITE, t2 WRITE; -SET DEBUG_SYNC = 'multi_update_reopen_tables SIGNAL parked WAIT_FOR go'; +# A stored routine could change after dispatch_command() +# but before a MDL lock is taken. This must be noticed and the +# sp cache flushed so the correct version can be loaded. +# +# Connection default +CREATE FUNCTION f1() RETURNS INT RETURN 1; +# Get f1 cached +SELECT f1(); +f1() +1 +# Then start executing it again... +SET DEBUG_SYNC= 'before_execute_sql_command SIGNAL before WAIT_FOR changed'; +# Sending: +SELECT f1(); +# Connection 2 +SET DEBUG_SYNC= 'now WAIT_FOR before'; +# ... but before f1 is locked, change it. +DROP FUNCTION f1; +CREATE FUNCTION f1() RETURNS INT RETURN 2; +SET DEBUG_SYNC= 'now SIGNAL changed'; +# Connection default +# We should now get '2' and not '1'. +# Reaping: SELECT f1() +f1() +2 +DROP FUNCTION f1; +SET DEBUG_SYNC= 'RESET'; +# +# Field translation items must be cleared in case of back-offs +# for queries that use Information Schema tables. Otherwise +# memory allocated in fix_fields() for views may end up referring +# to freed memory. +# +DROP FUNCTION IF EXISTS f1; +# Connection default +CREATE FUNCTION f1() RETURNS INT RETURN 0; +# Connection con2 +SET DEBUG_SYNC= 'after_wait_locked_pname SIGNAL locked WAIT_FOR issued'; +# con2 will now have an x-lock on f1 +# Sending: +ALTER FUNCTION f1 COMMENT 'comment'; +# Connection default +SET DEBUG_SYNC= 'now WAIT_FOR locked'; +# This query will block due to the x-lock on f1 and back-off +SHOW OPEN TABLES WHERE f1()=0; +# Connection con3 +# Check that the IS query is blocked before releasing the x-lock +SET DEBUG_SYNC= 'now SIGNAL issued'; +# Connection default +# Reaping: ALTER FUNCTION f1 COMMENT 'comment' +DROP FUNCTION f1; +SET DEBUG_SYNC= 'RESET'; +# +# Bug #48246 assert in close_thread_table +# +CREATE TABLE t1 (a INTEGER); +CREATE FUNCTION f1(b INTEGER) RETURNS INTEGER RETURN 1; +CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1; +INSERT INTO t1 VALUES(1), (2); +# Connection 2 CALL p1(); -DROP TABLE t1, t2; -SET DEBUG_SYNC = 'now WAIT_FOR parked'; -CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; -CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; -SET DEBUG_SYNC = 'now SIGNAL go'; -# Without the DEBUG_SYNC supplied in the same patch as this test in the -# code, this test statement will hang. -DROP TABLE t1, t2; +COUNT(f1(a)) +2 +# Connection default +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR called'; +# Sending: +CREATE TABLE t1 (a INTEGER); +# Connection 2 +SET DEBUG_SYNC= 'now WAIT_FOR locked'; +SET DEBUG_SYNC= 'before_open_table_wait_refresh SIGNAL called WAIT_FOR created'; +# This call used to cause an assertion. MDL locking conflict will +# cause back-off and retry. A variable indicating if a prelocking list +# exists, used to be not reset properly causing an eventual assert. +# Sending: +CALL p1(); +# Connection default +# Reaping: CREATE TABLE t1 (a INTEGER) +ERROR 42S01: Table 't1' already exists +SET DEBUG_SYNC= 'now SIGNAL created'; +# Connection 2 +# Reaping: CALL p1() +COUNT(f1(a)) +2 +# Connection default DROP PROCEDURE p1; -SET DEBUG_SYNC = 'RESET'; +DROP FUNCTION f1; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 3b34ef368e1..de7956eb500 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,7 +11,6 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically -sp_sync : Bug#48157 2010-02-06 5.5-m3 demands a differnt solution innodb-autoinc : Bug#49267 2009-12-02 test fails on windows because of different case mode innodb : Bug#49396 2009-12-03 test fails in embedded mode plugin_load : Bug#42144 2009-12-21 alik plugin_load fails diff --git a/mysql-test/t/sp-lock.test b/mysql-test/t/sp-lock.test index 0b31eabb0f1..7297790a886 100644 --- a/mysql-test/t/sp-lock.test +++ b/mysql-test/t/sp-lock.test @@ -893,6 +893,68 @@ disconnect con3; --source include/wait_until_disconnected.inc --echo # --> connection default connection default; + + +--echo # +--echo # SHOW CREATE PROCEDURE p1 called from p1, after p1 was altered +--echo # +--echo # We are just covering the existing behaviour with tests. The +--echo # results are not necessarily correct." +--echo # + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + SELECT get_lock("test", 10); + SHOW CREATE PROCEDURE p1; +END| +delimiter ;| + +connect (con2, localhost, root); +connect (con3, localhost, root); + +--echo # Connection default +connection default; +SELECT get_lock("test", 10); + +--echo # Connection 2 +connection con2; +--echo # Will halt before executing SHOW CREATE PROCEDURE p1 +--echo # Sending: +--send CALL p1() + +--echo # Connection 3 +connection con3; +let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist + WHERE state='User lock' and info='SELECT get_lock("test", 10)'; +--source include/wait_condition.inc +--echo # Alter p1 +DROP PROCEDURE p1; +CREATE PROCEDURE p1() BEGIN END; + +--echo # Connection default +connection default; +--echo # Resume CALL p1, now with new p1 +SELECT release_lock("test"); + +--echo # Connection 2 +connection con2; +--echo # Reaping: CALL p1() +--reap + +--echo # Connection 3 +connection con3; +disconnect con3; +--source include/wait_until_disconnected.inc +--echo # Connection 2 +connection con2; +disconnect con2; +--source include/wait_until_disconnected.inc +--echo # Connection default; +connection default; +DROP PROCEDURE p1; + + --echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/t/sp_sync.test b/mysql-test/t/sp_sync.test index 519a9211206..391298b604a 100644 --- a/mysql-test/t/sp_sync.test +++ b/mysql-test/t/sp_sync.test @@ -5,54 +5,156 @@ --source include/have_debug_sync.inc +# Save the initial number of concurrent sessions. +--source include/count_sessions.inc + +# Clean up resources used in this test case. +--disable_warnings +SET DEBUG_SYNC= 'RESET'; +--enable_warnings + --echo # ---echo # Bug#48157: crash in Item_field::used_tables +--echo # Bug #30977 Concurrent statement using stored function and +--echo # DROP FUNCTION breaks SBR +--echo # +--echo # A stored routine could change after dispatch_command() +--echo # but before a MDL lock is taken. This must be noticed and the +--echo # sp cache flushed so the correct version can be loaded. --echo # -CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; -CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; +connect (con2, localhost, root); -DELIMITER |; - -CREATE PROCEDURE p1() -BEGIN - UPDATE t1 JOIN t2 USING( a, b ) SET t1.b = 1, t2.b = 1; -END| - -DELIMITER ;| - -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); - -connection con1; -LOCK TABLES t1 WRITE, t2 WRITE; +--echo # Connection default +connection default; +CREATE FUNCTION f1() RETURNS INT RETURN 1; +--echo # Get f1 cached +SELECT f1(); +--echo # Then start executing it again... +SET DEBUG_SYNC= 'before_execute_sql_command SIGNAL before WAIT_FOR changed'; +--echo # Sending: +--send SELECT f1() +--echo # Connection 2 connection con2; -LET $ID= `select connection_id()`; -SET DEBUG_SYNC = 'multi_update_reopen_tables SIGNAL parked WAIT_FOR go'; ---send CALL p1() +SET DEBUG_SYNC= 'now WAIT_FOR before'; +--echo # ... but before f1 is locked, change it. +DROP FUNCTION f1; +CREATE FUNCTION f1() RETURNS INT RETURN 2; +SET DEBUG_SYNC= 'now SIGNAL changed'; -connection con1; -let $wait_condition= SELECT 1 FROM information_schema.processlist WHERE ID = $ID AND -state = "Waiting for table"; ---source include/wait_condition.inc -DROP TABLE t1, t2; -SET DEBUG_SYNC = 'now WAIT_FOR parked'; -CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b; -CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b; -SET DEBUG_SYNC = 'now SIGNAL go'; - -connection con2; +--echo # Connection default +--echo # We should now get '2' and not '1'. +connection default; +--echo # Reaping: SELECT f1() --reap -disconnect con1; disconnect con2; +DROP FUNCTION f1; +SET DEBUG_SYNC= 'RESET'; + +--echo # +--echo # Field translation items must be cleared in case of back-offs +--echo # for queries that use Information Schema tables. Otherwise +--echo # memory allocated in fix_fields() for views may end up referring +--echo # to freed memory. +--echo # + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +connect (con2, localhost, root); +connect (con3, localhost, root); + +--echo # Connection default connection default; +CREATE FUNCTION f1() RETURNS INT RETURN 0; ---echo # Without the DEBUG_SYNC supplied in the same patch as this test in the ---echo # code, this test statement will hang. -DROP TABLE t1, t2; +--echo # Connection con2 +connection con2; +SET DEBUG_SYNC= 'after_wait_locked_pname SIGNAL locked WAIT_FOR issued'; +--echo # con2 will now have an x-lock on f1 +--echo # Sending: +--send ALTER FUNCTION f1 COMMENT 'comment' + +--echo # Connection default +connection default; +SET DEBUG_SYNC= 'now WAIT_FOR locked'; +--disable_result_log +--echo # This query will block due to the x-lock on f1 and back-off +--send SHOW OPEN TABLES WHERE f1()=0 + +--echo # Connection con3 +connection con3; +let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist + WHERE state= 'Waiting for table' + AND info='SHOW OPEN TABLES WHERE f1()=0'; +--source include/wait_condition.inc +--echo # Check that the IS query is blocked before releasing the x-lock +SET DEBUG_SYNC= 'now SIGNAL issued'; + +--echo # Connection default +connection default; +--echo # Reaping: ALTER FUNCTION f1 COMMENT 'comment' +--reap +--enable_result_log +DROP FUNCTION f1; +SET DEBUG_SYNC= 'RESET'; +disconnect con2; +disconnect con3; + + +--echo # +--echo # Bug #48246 assert in close_thread_table +--echo # + +CREATE TABLE t1 (a INTEGER); +CREATE FUNCTION f1(b INTEGER) RETURNS INTEGER RETURN 1; +CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1; + +INSERT INTO t1 VALUES(1), (2); + +--echo # Connection 2 +connect (con2, localhost, root); +CALL p1(); + +--echo # Connection default +connection default; +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR called'; +--echo # Sending: +--send CREATE TABLE t1 (a INTEGER) + +--echo # Connection 2 +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR locked'; +SET DEBUG_SYNC= 'before_open_table_wait_refresh SIGNAL called WAIT_FOR created'; +--echo # This call used to cause an assertion. MDL locking conflict will +--echo # cause back-off and retry. A variable indicating if a prelocking list +--echo # exists, used to be not reset properly causing an eventual assert. +--echo # Sending: +--send CALL p1() + +--echo # Connection default +connection default; +--echo # Reaping: CREATE TABLE t1 (a INTEGER) +--error ER_TABLE_EXISTS_ERROR +--reap +SET DEBUG_SYNC= 'now SIGNAL created'; + +--echo # Connection 2 +connection con2; +--echo # Reaping: CALL p1() +--reap; + +--echo # Connection default +connection default; +disconnect con2; DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; -SET DEBUG_SYNC = 'RESET'; +# Check that all connections opened by test cases in this file are really +# gone so execution of other tests won't be affected by their presence. +--source include/wait_until_count_sessions.inc diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 23e0d8c0d70..06acfab0537 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -31,6 +31,7 @@ #include "transaction.h" #include "sql_audit.h" #include "sql_prepare.h" +#include "debug_sync.h" #include "probes_mysql.h" #include "set_var.h" @@ -2115,6 +2116,11 @@ mysql_execute_command(THD *thd) if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE)) goto error; +#ifndef DBUG_OFF + if (lex->sql_command != SQLCOM_SET_OPTION) + DEBUG_SYNC(thd,"before_execute_sql_command"); +#endif + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: