Commit 8f21a316 authored by Kristian Nielsen's avatar Kristian Nielsen

MDEV-6435: Assertion `m_status == DA_ERROR' failed in...

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.
parent 45f6262f
......@@ -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
......@@ -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
......@@ -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)
{
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment