diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index ad5a792173a..b122d888c6d 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -649,7 +649,6 @@ void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton); void thd_storage_lock_wait(MYSQL_THD thd, long long value); int thd_tx_isolation(const MYSQL_THD thd); int thd_tx_is_read_only(const MYSQL_THD thd); -int thd_rpl_is_parallel(const MYSQL_THD thd); /** Create a temporary file. diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 02fe3b75227..de4356af740 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -518,7 +518,6 @@ void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value); int thd_tx_isolation(const void* thd); int thd_tx_is_read_only(const void* thd); -int thd_rpl_is_parallel(const void* thd); int mysql_tmpfile(const char *prefix); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 6aba0ddb889..e515699cad6 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -518,7 +518,6 @@ void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value); int thd_tx_isolation(const void* thd); int thd_tx_is_read_only(const void* thd); -int thd_rpl_is_parallel(const void* thd); int mysql_tmpfile(const char *prefix); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index 1f7b4e90908..7defe0aec2c 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -518,7 +518,6 @@ void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value); int thd_tx_isolation(const void* thd); int thd_tx_is_read_only(const void* thd); -int thd_rpl_is_parallel(const void* thd); int mysql_tmpfile(const char *prefix); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index afc4a597b0f..a36f51e74e1 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -472,7 +472,6 @@ void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value); int thd_tx_isolation(const void* thd); int thd_tx_is_read_only(const void* thd); -int thd_rpl_is_parallel(const void* thd); int mysql_tmpfile(const char *prefix); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index 0d2c0719b87..9701ad1b92f 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -518,7 +518,6 @@ void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value); int thd_tx_isolation(const void* thd); int thd_tx_is_read_only(const void* thd); -int thd_rpl_is_parallel(const void* thd); int mysql_tmpfile(const char *prefix); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); diff --git a/mysql-test/suite/binlog/r/binlog_killed.result b/mysql-test/suite/binlog/r/binlog_killed.result index cda4e8ad6f4..d751b1f9002 100644 --- a/mysql-test/suite/binlog/r/binlog_killed.result +++ b/mysql-test/suite/binlog/r/binlog_killed.result @@ -179,6 +179,97 @@ RELEASE_LOCK("a") 1 drop table t4; drop function bug27563; +FLUSH LOGS; +connect con3, localhost, root,,; +connection con3; +MI: MyISAM, INNODB +BEGIN; +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); +connection con1; +KILL ID; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION +master-bin.000002 # Gtid_list # # [#-#-#] +master-bin.000002 # Binlog_checkpoint # # master-bin.000001 +master-bin.000002 # Binlog_checkpoint # # master-bin.000002 +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=3 +master-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (NULL, 1) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=4 +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (NULL, 1) +master-bin.000002 # Query # # ROLLBACK +disconnect con3; +connect con3, localhost, root,,; +connection con3; +IM: INNODB, MyISAM +BEGIN; +INSERT INTO t1 VALUES (NULL, 1); +INSERT INTO t2 VALUES (NULL, 1); +connection con1; +KILL ID; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=4 +master-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (NULL, 1) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=5 +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (NULL, 1) +master-bin.000002 # Query # # ROLLBACK +disconnect con3; +connect con3, localhost, root,,; +connection con3; +IMI: INNODB, MyISAM, INNODB +BEGIN; +INSERT INTO t1 VALUES (NULL, 1); +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); +connection con1; +KILL ID; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=5 +master-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (NULL, 1) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=6 +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (NULL, 1) +master-bin.000002 # Intvar # # INSERT_ID=7 +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (NULL, 1) +master-bin.000002 # Query # # ROLLBACK +disconnect con3; +connect con3, localhost, root,,; +connection con3; +MI2: MyISAM, INNODB, MyISAM, INNODB +BEGIN; +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); +connection con1; +KILL ID; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=6 +master-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (NULL, 1) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=7 +master-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (NULL, 1) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=8 +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (NULL, 1) +master-bin.000002 # Intvar # # INSERT_ID=9 +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (NULL, 1) +master-bin.000002 # Query # # ROLLBACK connection default; disconnect con1; disconnect con2; diff --git a/mysql-test/suite/binlog/r/load_data_stm_view.result b/mysql-test/suite/binlog/r/load_data_stm_view.result index ddbdb71983f..c21ffb7dcc6 100644 --- a/mysql-test/suite/binlog/r/load_data_stm_view.result +++ b/mysql-test/suite/binlog/r/load_data_stm_view.result @@ -1,3 +1,4 @@ +reset master; create table t1 (i int, j int); create view v1 as select i from t1; LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/3940.data' INTO TABLE v1 (i); diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test index 73759ee5aa5..8ac223603a3 100644 --- a/mysql-test/suite/binlog/t/binlog_killed.test +++ b/mysql-test/suite/binlog/t/binlog_killed.test @@ -349,6 +349,87 @@ drop table t4; drop function bug27563; +# Prove that killing connection in the middle +# of mixed engine transactions affect binlogging +# as specified. + +# keep binlogging for this piece of test in a new file +FLUSH LOGS; + +# Connection con3 as transaction generator thoughout the test +connect (con3, localhost, root,,); + +connection con3; +let $ID= `select connection_id()`; + +--echo MI: MyISAM, INNODB +BEGIN; +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); + +#Connection con1 as killer throughout the test +connection con1; +--replace_result $ID ID +--eval KILL $ID +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +--let $binlog_start= 4 +--source include/show_binlog_events.inc +--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1) + +disconnect con3; +connect (con3, localhost, root,,); +connection con3; +let $ID= `select connection_id()`; + +--echo IM: INNODB, MyISAM +BEGIN; +INSERT INTO t1 VALUES (NULL, 1); +INSERT INTO t2 VALUES (NULL, 1); + +connection con1; +--replace_result $ID ID +--eval KILL $ID +--let $binlog_start= $binlog_killed_pos +--source include/show_binlog_events.inc +--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1) + +disconnect con3; +connect (con3, localhost, root,,); +connection con3; +let $ID= `select connection_id()`; + +--echo IMI: INNODB, MyISAM, INNODB +BEGIN; +INSERT INTO t1 VALUES (NULL, 1); +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); + +connection con1; +--replace_result $ID ID +--eval KILL $ID +--let $binlog_start= $binlog_killed_pos +--source include/show_binlog_events.inc +--let $binlog_killed_pos=query_get_value(SHOW MASTER STATUS, Position, 1) + +disconnect con3; +connect (con3, localhost, root,,); +connection con3; +let $ID= `select connection_id()`; + +--echo MI2: MyISAM, INNODB, MyISAM, INNODB +BEGIN; +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); +INSERT INTO t2 VALUES (NULL, 1); +INSERT INTO t1 VALUES (NULL, 1); + +connection con1; +--replace_result $ID ID +--eval KILL $ID +--let $binlog_start= $binlog_killed_pos +--source include/show_binlog_events.inc + + # # common cleanup # diff --git a/mysql-test/suite/binlog/t/load_data_stm_view.test b/mysql-test/suite/binlog/t/load_data_stm_view.test index b70651b4e2d..9f64b813eec 100644 --- a/mysql-test/suite/binlog/t/load_data_stm_view.test +++ b/mysql-test/suite/binlog/t/load_data_stm_view.test @@ -8,6 +8,8 @@ 1 EOF +reset master; + create table t1 (i int, j int); create view v1 as select i from t1; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR @@ -15,6 +17,8 @@ create view v1 as select i from t1; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/3940.data' INTO TABLE v1 select * from v1; +--let $binlog_file = LAST --source include/show_binlog_events.inc drop view v1; drop table t1; +--remove_file $MYSQLTEST_VARDIR/3940.data diff --git a/sql/log.cc b/sql/log.cc index 704450aa547..e5ff85e4544 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4171,14 +4171,6 @@ bool MYSQL_BIN_LOG::reset_logs(THD *thd, bool create_new_log, mysql_mutex_unlock(&LOCK_xid_list); } - /* - The following mutex is needed to ensure that no threads call - 'delete thd' as we would then risk missing a 'rollback' from this - thread. If the transaction involved MyISAM tables, it should go - into binlog even on rollback. - */ - mysql_mutex_lock(&LOCK_thread_count); - /* Save variables so that we can reopen the log */ save_name=name; name=0; // Protect against free @@ -4285,7 +4277,6 @@ bool MYSQL_BIN_LOG::reset_logs(THD *thd, bool create_new_log, err: if (error == 1) name= const_cast(save_name); - mysql_mutex_unlock(&LOCK_thread_count); if (!is_relay_log) { diff --git a/sql/slave.cc b/sql/slave.cc index 97117656db8..1ee745ced6a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4967,9 +4967,7 @@ err_during_init: // TODO: make rpl_status part of Master_info change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE); - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); - mysql_mutex_unlock(&LOCK_thread_count); + thd->assert_not_linked(); delete thd; thread_safe_decrement32(&service_thread_count); signal_thd_deleted(); @@ -5648,11 +5646,7 @@ err_during_init: rpl_parallel_resize_pool_if_no_slaves(); - /* TODO: Check if this lock is needed */ - mysql_mutex_lock(&LOCK_thread_count); delete serial_rgi; - mysql_mutex_unlock(&LOCK_thread_count); - delete thd; thread_safe_decrement32(&service_thread_count); signal_thd_deleted(); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7fd07e0e545..a08078c5cff 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -878,6 +878,12 @@ void close_thread_table(THD *thd, TABLE **table_ptr) table->file->update_global_index_stats(); } + /* + This look is needed to allow THD::notify_shared_lock() to + traverse the thd->open_tables list without having to worry that + some of the tables are removed from under it + */ + mysql_mutex_lock(&thd->LOCK_thd_data); *table_ptr=table->next; mysql_mutex_unlock(&thd->LOCK_thd_data); @@ -8392,84 +8398,6 @@ my_bool mysql_rm_tmp_tables(void) unireg support functions *****************************************************************************/ -/** - A callback to the server internals that is used to address - special cases of the locking protocol. - Invoked when acquiring an exclusive lock, for each thread that - has a conflicting shared metadata lock. - - This function: - - aborts waiting of the thread on a data lock, to make it notice - the pending exclusive lock and back off. - - if the thread is an INSERT DELAYED thread, sends it a KILL - signal to terminate it. - - @note This function does not wait for the thread to give away its - locks. Waiting is done outside for all threads at once. - - @param thd Current thread context - @param in_use The thread to wake up - @param needs_thr_lock_abort Indicates that to wake up thread - this call needs to abort its waiting - on table-level lock. - - @retval TRUE if the thread was woken up - @retval FALSE otherwise. - - @note It is one of two places where border between MDL and the - rest of the server is broken. -*/ - -bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, - bool needs_thr_lock_abort) -{ - bool signalled= FALSE; - if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && - !in_use->killed) - { - in_use->set_killed(KILL_SYSTEM_THREAD); - mysql_mutex_lock(&in_use->mysys_var->mutex); - if (in_use->mysys_var->current_cond) - { - mysql_mutex_lock(in_use->mysys_var->current_mutex); - mysql_cond_broadcast(in_use->mysys_var->current_cond); - mysql_mutex_unlock(in_use->mysys_var->current_mutex); - } - mysql_mutex_unlock(&in_use->mysys_var->mutex); - signalled= TRUE; - } - - if (needs_thr_lock_abort) - { - mysql_mutex_lock(&in_use->LOCK_thd_data); - for (TABLE *thd_table= in_use->open_tables; - thd_table ; - thd_table= thd_table->next) - { - /* - Check for TABLE::needs_reopen() is needed since in some places we call - handler::close() for table instance (and set TABLE::db_stat to 0) - and do not remove such instances from the THD::open_tables - for some time, during which other thread can see those instances - (e.g. see partitioning code). - */ - if (!thd_table->needs_reopen()) - { - signalled|= mysql_lock_abort_for_thread(thd, thd_table); - if (thd && WSREP(thd) && wsrep_thd_is_BF(thd, true)) - { - WSREP_DEBUG("remove_table_from_cache: %llu", - (unsigned long long) thd->real_id); - wsrep_abort_thd((void *)thd, (void *)in_use, FALSE); - } - } - } - mysql_mutex_unlock(&in_use->LOCK_thd_data); - } - return signalled; -} - - int setup_ftfuncs(SELECT_LEX *select_lex) { List_iterator li(*(select_lex->ftfunc_list)), diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9181e3c96d6..628671802a0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4775,13 +4775,6 @@ extern "C" int thd_slave_thread(const MYSQL_THD thd) return(thd->slave_thread); } -/* Returns true for a worker thread in parallel replication. */ -extern "C" int thd_rpl_is_parallel(const MYSQL_THD thd) -{ - return thd->rgi_slave && thd->rgi_slave->is_parallel_exec; -} - - /* Returns high resolution timestamp for the start of the current query. */ extern "C" unsigned long long thd_start_utime(const MYSQL_THD thd) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 32695a450c4..627e349c50b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2423,8 +2423,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) The thread could be killed with an error message if di->handle_inserts() or di->open_and_lock_table() fails. The thread could be killed without an error message if - killed using mysql_notify_thread_having_shared_lock() or - kill_delayed_threads_for_table(). + killed using kill_delayed_threads_for_table(). */ if (!thd.is_error()) my_message(ER_QUERY_INTERRUPTED, ER_THD(&thd, ER_QUERY_INTERRUPTED), diff --git a/sql/sql_list.h b/sql/sql_list.h index 422b7943aa9..c708ed6d2f9 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -622,6 +622,10 @@ struct ilink { DBUG_ASSERT(prev != 0 && next != 0); } + inline void assert_not_linked() + { + DBUG_ASSERT(prev == 0 && next == 0); + } virtual ~ilink() { unlink(); } /*lint -e1740 */ };