diff options
author | Kristian Nielsen <knielsen@knielsen-hq.org> | 2014-07-10 13:55:53 +0200 |
---|---|---|
committer | Kristian Nielsen <knielsen@knielsen-hq.org> | 2014-07-10 13:55:53 +0200 |
commit | 8f21a3166908d71b5828d50bfce65b480508c6c1 (patch) | |
tree | c4aff2031f1402155445fb5cf4e5e29c5dcb1774 | |
parent | 45f6262f54c5d1ef535c0529c399a7352b5fdea4 (diff) | |
download | mariadb-git-8f21a3166908d71b5828d50bfce65b480508c6c1.tar.gz |
MDEV-6435: Assertion `m_status == DA_ERROR' failed in Diagnostics_area::sql_errno() with parallel replication
When a MyISAM query is killed midway, the query is logged to the binlog marked
with the error.
The slave does not attempt to run the query, but aborts with a suitable error
message in the error log for the DBA to act on.
In this case, the parallel replication code would check the sql_errno() code,
even no my_error() had been set. In debug builds, this causes an assertion.
Fixed the code to check that we actually have an error set before querying for
an error code.
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_parallel.result | 28 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_parallel.test | 50 | ||||
-rw-r--r-- | sql/rpl_parallel.cc | 5 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 |
4 files changed, 82 insertions, 3 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result index 70ac0b579f3..1c686e44a25 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel.result +++ b/mysql-test/suite/rpl/r/rpl_parallel.result @@ -819,11 +819,37 @@ test_check OK test_check OK +*** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error *** +CREATE TABLE t6 (a INT) ENGINE=MyISAM; +CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1; +SET @old_format= @@binlog_format; +SET binlog_format= statement; +SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont'; +INSERT INTO t6 VALUES (1), (2), (3); +SET debug_sync='now WAIT_FOR ready'; +KILL QUERY CONID; +SET debug_sync='now SIGNAL cont'; +ERROR 70100: Query execution was interrupted +SET binlog_format= @old_format; +SET debug_sync='RESET'; +SET debug_sync='RESET'; +include/wait_for_slave_sql_error.inc [errno=1317] +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_slave_pos= 'AFTER_ERROR_GTID_POS'; +include/start_slave.inc +INSERT INTO t6 VALUES (4); +SELECT * FROM t6 ORDER BY a; +a +1 +4 +SELECT * FROM t6 ORDER BY a; +a +4 include/stop_slave.inc SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc SET DEBUG_SYNC= 'RESET'; DROP function foo; -DROP TABLE t1,t2,t3,t4,t5; +DROP TABLE t1,t2,t3,t4,t5,t6; SET DEBUG_SYNC= 'RESET'; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test index 09111fb7461..0f679fa18ee 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel.test +++ b/mysql-test/suite/rpl/t/rpl_parallel.test @@ -1292,6 +1292,54 @@ eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS t --enable_query_log +--echo *** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error *** + +--connection server_1 +CREATE TABLE t6 (a INT) ENGINE=MyISAM; +CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1; + +--connection con1 +SET @old_format= @@binlog_format; +SET binlog_format= statement; +--let $conid = `SELECT CONNECTION_ID()` +SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont'; +send INSERT INTO t6 VALUES (1), (2), (3); + +--connection server_1 +SET debug_sync='now WAIT_FOR ready'; +--replace_result $conid CONID +eval KILL QUERY $conid; +SET debug_sync='now SIGNAL cont'; + +--connection con1 +--error ER_QUERY_INTERRUPTED +--reap +SET binlog_format= @old_format; +SET debug_sync='RESET'; +--let $after_error_gtid_pos= `SELECT @@gtid_binlog_pos` + +--connection server_1 +SET debug_sync='RESET'; + + +--connection server_2 +--let $slave_sql_errno= 1317 +--source include/wait_for_slave_sql_error.inc +STOP SLAVE IO_THREAD; +--replace_result $after_error_gtid_pos AFTER_ERROR_GTID_POS +eval SET GLOBAL gtid_slave_pos= '$after_error_gtid_pos'; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t6 VALUES (4); +SELECT * FROM t6 ORDER BY a; +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t6 ORDER BY a; + + --connection server_2 --source include/stop_slave.inc SET GLOBAL slave_parallel_threads=@old_parallel_threads; @@ -1300,7 +1348,7 @@ SET DEBUG_SYNC= 'RESET'; --connection server_1 DROP function foo; -DROP TABLE t1,t2,t3,t4,t5; +DROP TABLE t1,t2,t3,t4,t5,t6; SET DEBUG_SYNC= 'RESET'; --source include/rpl_end.inc diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 98753865568..0d23248539c 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -234,8 +234,11 @@ static void convert_kill_to_deadlock_error(rpl_group_info *rgi) { THD *thd= rgi->thd; - int err_code= thd->get_stmt_da()->sql_errno(); + int err_code; + if (!thd->get_stmt_da()->is_error()) + return; + err_code= thd->get_stmt_da()->sql_errno(); if ((err_code == ER_QUERY_INTERRUPTED || err_code == ER_CONNECTION_KILLED) && rgi->killed_for_retry) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 8a9e8ddc816..73218b4fda8 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -43,6 +43,7 @@ #include "sql_base.h" // close_thread_tables #include "transaction.h" // trans_commit_stmt #include "sql_audit.h" +#include "debug_sync.h" /* Sufficient max length of printed destinations and frame offsets (all uints). @@ -1309,6 +1310,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) /* Discard the initial part of executing routines. */ thd->profiling.discard_current_query(); #endif + DEBUG_SYNC(thd, "sp_head_execute_before_loop"); do { sp_instr *i; |