diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc new file mode 100644 index 00000000000..fed97195aba --- /dev/null +++ b/mysql-test/include/wait_for_slave_param.inc @@ -0,0 +1,26 @@ +# include/wait_for_slave_param.inc +# +# SUMMARY +# +# Waits until SHOW SLAVE STATUS has returned a spicified value. +# +# USAGE +# +# let $slave_param= Slave_SQL_Running; +# let $slave_param_value= No; +# --source include/slave_wait_param.inc + +let $slave_wait_param_counter= 300; +let $slave_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1); +while (`select "$slave_value" != "$slave_param_value"`) +{ + dec $slave_wait_param_counter; + if (!$slave_wait_param_counter) + { + --echo ERROR: failed while waiting for slave parameter $slave_param: $slave_param_value + query_vertical show slave status; + exit; + } + sleep 0.1; + let $slave_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1); +} diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result index 7eb7fd16edb..dcbffd6f7c8 100644 --- a/mysql-test/r/flush.result +++ b/mysql-test/r/flush.result @@ -55,3 +55,19 @@ flush tables with read lock; insert into t2 values(1); unlock tables; drop table t1, t2; +End of 5.0 tests +set @old_general_log= @@general_log; +set @old_read_only= @@read_only; +set global general_log= on; +flush tables with read lock; +flush logs; +unlock tables; +set global read_only=1; +flush logs; +unlock tables; +flush tables with read lock; +flush logs; +unlock tables; +set global general_log= @old_general_log; +set global read_only= @old_read_only; +End of 5.1 tests diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result index 28ddbaf33a0..7543814578a 100644 --- a/mysql-test/r/rpl_log_pos.result +++ b/mysql-test/r/rpl_log_pos.result @@ -7,27 +7,80 @@ start slave; show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 106 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 106 # # master-bin.000001 Yes Yes 0 0 106 # None 0 No # No -stop slave; -change master to master_log_pos=75; -start slave; stop slave; change master to master_log_pos=75; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 75 # # master-bin.000001 No No 0 0 75 # None 0 No # No +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 75 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 75 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No start slave; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 75 # # master-bin.000001 No Yes 0 0 75 # None 0 No # No stop slave; -change master to master_log_pos=178; -start slave; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 178 # # master-bin.000001 # Yes 0 0 178 # None 0 No # No +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 75 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 75 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 106 @@ -35,7 +88,6 @@ create table if not exists t1 (n int); drop table if exists t1; create table t1 (n int); insert into t1 values (1),(2),(3); -stop slave; change master to master_log_pos=106; start slave; select * from t1 ORDER BY n; @@ -44,3 +96,4 @@ n 2 3 drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/rpl_ssl.result b/mysql-test/r/rpl_ssl.result index 908f0020188..64d52d63f78 100644 --- a/mysql-test/r/rpl_ssl.result +++ b/mysql-test/r/rpl_ssl.result @@ -96,3 +96,4 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No drop user replssl@localhost; drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index 3a4f2f2f5f2..d58d038c3ea 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -133,4 +133,28 @@ disconnect con3; connection default; drop table t1, t2; -# End of 5.0 tests +--echo End of 5.0 tests + +# +# Bug #26380: LOCK TABLES + FLUSH LOGS causes deadlock +# +set @old_general_log= @@general_log; +set @old_read_only= @@read_only; +set global general_log= on; + +flush tables with read lock; +flush logs; +unlock tables; + +set global read_only=1; +flush logs; +unlock tables; + +flush tables with read lock; +flush logs; +unlock tables; + +set global general_log= @old_general_log; +set global read_only= @old_read_only; + +--echo End of 5.1 tests diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test index b98d89c1dc3..2c6c1d9868d 100644 --- a/mysql-test/t/rpl_log_pos.test +++ b/mysql-test/t/rpl_log_pos.test @@ -14,31 +14,29 @@ source include/master-slave.inc; --replace_column 3 show master status; sync_slave_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; -stop slave; -change master to master_log_pos=75; -start slave; -sleep 5; + stop slave; +--source include/wait_for_slave_to_stop.inc change master to master_log_pos=75; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; +query_vertical show slave status; + start slave; -sleep 5; +let $slave_param= Slave_SQL_Running; +let $slave_param_value= Yes; +--source include/wait_for_slave_param.inc +let $slave_param= Slave_IO_Running; +let $slave_param_value= No; +--source include/wait_for_slave_param.inc +stop slave; +--source include/wait_for_slave_to_stop.inc + --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; -stop slave; -change master to master_log_pos=178; -start slave; -sleep 2; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 11 # 23 # 33 # -show slave status; +query_vertical show slave status; + connection master; --replace_column 3 show master status; @@ -48,7 +46,6 @@ create table t1 (n int); insert into t1 values (1),(2),(3); save_master_pos; connection slave; -stop slave; change master to master_log_pos=106; start slave; sync_with_master; @@ -57,4 +54,4 @@ connection master; drop table t1; sync_slave_with_master; -# End of 4.1 tests +--echo End of 5.0 tests diff --git a/mysql-test/t/rpl_ssl.test b/mysql-test/t/rpl_ssl.test index dd03d5533b0..a0317028557 100644 --- a/mysql-test/t/rpl_ssl.test +++ b/mysql-test/t/rpl_ssl.test @@ -58,6 +58,7 @@ connection master; # the sync has something to do insert into t1 values (NULL); sync_slave_with_master; +--source include/wait_for_slave_to_start.inc --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # query_vertical show slave status; @@ -67,3 +68,4 @@ drop user replssl@localhost; drop table t1; sync_slave_with_master; +--echo End of 5.0 tests diff --git a/sql/lock.cc b/sql/lock.cc index 08c109a17ab..50922a682a2 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -92,6 +92,7 @@ static void print_lock_error(int error, const char *); count The number of tables to lock. flags Options: MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK Ignore a global read lock + MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY Ignore SET GLOBAL READ_ONLY MYSQL_LOCK_IGNORE_FLUSH Ignore a flush tables. MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN Instead of reopening altered or dropped tables by itself, @@ -150,11 +151,11 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, } } - if ( write_lock_used - && opt_readonly - && ! (thd->security_ctx->master_access & SUPER_ACL) - && ! thd->slave_thread - ) + if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) && + write_lock_used && + opt_readonly && + !(thd->security_ctx->master_access & SUPER_ACL) && + !thd->slave_thread) { /* Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock. @@ -714,9 +715,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, if (!table_ptr[i]-> file-> check_if_locking_is_allowed(thd->lex->sql_command, thd->lex->type, table_ptr[i], count, i, &system_count, - (thd == logger.get_general_log_thd()) || - (thd == logger.get_slow_log_thd()) || - (thd == logger.get_privileged_thread()))) + logger.is_privileged_thread(thd))) DBUG_RETURN(0); } diff --git a/sql/log.h b/sql/log.h index 25bcbd6c62d..d92e0117bcc 100644 --- a/sql/log.h +++ b/sql/log.h @@ -600,6 +600,12 @@ public: else return NULL; } + bool is_privileged_thread(THD *thd) + { + return thd == get_general_log_thd() || + thd == get_slow_log_thd() || + thd == get_privileged_thread(); + } }; enum enum_binlog_format { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index abf7811b953..83244d3aeff 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1765,6 +1765,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, #define MYSQL_LOCK_IGNORE_FLUSH 0x0002 #define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004 #define MYSQL_OPEN_TEMPORARY_ONLY 0x0008 +#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0010 void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b798106082a..9b336e8a703 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4018,6 +4018,12 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once TABLE **start,**ptr; + uint lock_flag= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN; + + /* Ignore GLOBAL READ LOCK and GLOBAL READ_ONLY if called from a logger */ + if (logger.is_privileged_thread(thd)) + lock_flag|= (MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK | + MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY); if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count))) DBUG_RETURN(-1); @@ -4046,8 +4052,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) } if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), - MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, - need_reopen))) + lock_flag, need_reopen))) { if (thd->lex->requires_prelocking()) {