mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 21:12:26 +01:00
Merge aelkin@bk-internal.mysql.com:/home/bk/mysql-5.0-rpl
into koti.dsl.inet.fi:/home/elkin/MySQL/TEAM/FIXES/5.0/bug27571_asyn_killed_flags
This commit is contained in:
commit
f974872f5c
12 changed files with 509 additions and 203 deletions
|
@ -9,4 +9,110 @@ insert into t2 values (null, null), (null, get_lock("a", 10));
|
||||||
select @result /* must be zero either way */;
|
select @result /* must be zero either way */;
|
||||||
@result
|
@result
|
||||||
0
|
0
|
||||||
|
delete from t1;
|
||||||
|
delete from t2;
|
||||||
|
insert into t1 values (1,1),(2,2);
|
||||||
|
begin;
|
||||||
|
update t1 set b=11 where a=2;
|
||||||
|
update t1 set b=b+10;
|
||||||
|
kill query ID;
|
||||||
|
rollback;
|
||||||
|
ERROR 70100: Query execution was interrupted
|
||||||
|
select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
begin;
|
||||||
|
delete from t1 where a=2;
|
||||||
|
delete from t1 where a=2;
|
||||||
|
kill query ID;
|
||||||
|
rollback;
|
||||||
|
ERROR 70100: Query execution was interrupted
|
||||||
|
select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
drop table if exists t4;
|
||||||
|
create table t4 (a int, b int) engine=innodb;
|
||||||
|
insert into t4 values (3, 3);
|
||||||
|
begin;
|
||||||
|
insert into t1 values (3, 3);
|
||||||
|
begin;
|
||||||
|
insert into t1 select * from t4 for update;
|
||||||
|
kill query ID;
|
||||||
|
rollback;
|
||||||
|
ERROR 70100: Query execution was interrupted
|
||||||
|
rollback;
|
||||||
|
select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
drop table t4;
|
||||||
|
create function bug27563(n int)
|
||||||
|
RETURNS int(11)
|
||||||
|
DETERMINISTIC
|
||||||
|
begin
|
||||||
|
if n > 1 then
|
||||||
|
select get_lock("a", 10) into @a;
|
||||||
|
end if;
|
||||||
|
return n;
|
||||||
|
end|
|
||||||
|
delete from t2;
|
||||||
|
insert into t2 values (1,1), (2,2);
|
||||||
|
reset master;
|
||||||
|
select get_lock("a", 20);
|
||||||
|
get_lock("a", 20)
|
||||||
|
1
|
||||||
|
update t2 set b=b + bug27563(b) order by a;
|
||||||
|
kill query ID;
|
||||||
|
ERROR 70100: Query execution was interrupted
|
||||||
|
select * from t2 /* must be (1,2), (2,2) */;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
2 2
|
||||||
|
show master status /* must have the update event more to FD */;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 211
|
||||||
|
select
|
||||||
|
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null;
|
||||||
|
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null
|
||||||
|
1
|
||||||
|
select 0 /* must return 0 to mean the killed query is in */;
|
||||||
|
0
|
||||||
|
0
|
||||||
|
select RELEASE_LOCK("a");
|
||||||
|
RELEASE_LOCK("a")
|
||||||
|
1
|
||||||
|
delete from t2;
|
||||||
|
insert into t2 values (1,1), (2,2);
|
||||||
|
reset master;
|
||||||
|
select get_lock("a", 20);
|
||||||
|
get_lock("a", 20)
|
||||||
|
1
|
||||||
|
delete from t2 where a=1 or a=bug27563(2) order by a;
|
||||||
|
kill query ID;
|
||||||
|
ERROR 70100: Query execution was interrupted
|
||||||
|
select * from t2 /* must be (1,2), (2,2) */;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
show master status /* must have the update event more to FD */;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 98
|
||||||
|
select
|
||||||
|
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null;
|
||||||
|
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null
|
||||||
|
1
|
||||||
|
select 0 /* must return 0 to mean the killed query is in */;
|
||||||
|
0
|
||||||
|
0
|
||||||
|
select RELEASE_LOCK("a");
|
||||||
|
RELEASE_LOCK("a")
|
||||||
|
1
|
||||||
|
drop function bug27563;
|
||||||
drop table t1,t2,t3;
|
drop table t1,t2,t3;
|
||||||
|
end of the tests
|
||||||
|
|
|
@ -55,194 +55,239 @@ enable_result_log;
|
||||||
|
|
||||||
select @result /* must be zero either way */;
|
select @result /* must be zero either way */;
|
||||||
|
|
||||||
# the functions are either *insensitive* to killing or killing can cause
|
|
||||||
# strange problmes with the error propagation out of SF's stack
|
--remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
|
||||||
# Bug#27563, Bug#27565, BUG#24971
|
|
||||||
#
|
#
|
||||||
# TODO: use if's block as regression test for the bugs or remove
|
# bug#27571 asynchronous setting mysql_`query`::error and Query_log_e::error_code
|
||||||
#
|
#
|
||||||
if (0)
|
|
||||||
{
|
# checking that killing inside of select loops is safe as before
|
||||||
|
# killing after the loop can be only simulated - another test
|
||||||
|
|
||||||
|
delete from t1;
|
||||||
|
delete from t2;
|
||||||
|
insert into t1 values (1,1),(2,2);
|
||||||
|
let $ID= `select connection_id()`;
|
||||||
|
|
||||||
|
#
|
||||||
|
# simple update
|
||||||
|
#
|
||||||
|
connection con1;
|
||||||
|
begin; update t1 set b=11 where a=2;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
send update t1 set b=b+10;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--replace_result $ID ID
|
||||||
|
eval kill query $ID;
|
||||||
|
rollback;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
--error ER_QUERY_INTERRUPTED
|
||||||
|
reap;
|
||||||
|
select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
|
||||||
|
#
|
||||||
|
# multi update
|
||||||
|
# commented out as Bug #31807 multi-update,delete killing does not report with ER_QUERY_INTERRUPTED
|
||||||
|
# in the way
|
||||||
|
#
|
||||||
|
# connection con1;
|
||||||
|
# begin; update t1 set b=b+10;
|
||||||
|
|
||||||
|
# connection con2;
|
||||||
|
# send update t1 as t_1,t1 as t_2 set t_1.b=11 where t_2.a=2;
|
||||||
|
|
||||||
|
# connection con1;
|
||||||
|
# --replace_result $ID ID
|
||||||
|
# eval kill query $ID;
|
||||||
|
# rollback;
|
||||||
|
|
||||||
|
# disable_abort_on_error;
|
||||||
|
|
||||||
|
# connection con2;
|
||||||
|
# --error HY000,ER_QUERY_INTERRUPTED
|
||||||
|
# reap;
|
||||||
|
# select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
|
||||||
|
# enable_abort_on_error;
|
||||||
|
#
|
||||||
|
# simple delete
|
||||||
|
#
|
||||||
|
connection con1;
|
||||||
|
begin; delete from t1 where a=2;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
send delete from t1 where a=2;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--replace_result $ID ID
|
||||||
|
eval kill query $ID;
|
||||||
|
rollback;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
--error ER_QUERY_INTERRUPTED
|
||||||
|
reap;
|
||||||
|
select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
|
||||||
|
#
|
||||||
|
# multi delete
|
||||||
|
# the same as for multi-update
|
||||||
|
#
|
||||||
|
# connection con1;
|
||||||
|
# begin; delete from t1 where a=2;
|
||||||
|
|
||||||
|
# connection con2;
|
||||||
|
# send delete t1 from t1 where t1.a=2;
|
||||||
|
|
||||||
|
# connection con1;
|
||||||
|
# --replace_result $ID ID
|
||||||
|
# eval kill query $ID;
|
||||||
|
# rollback;
|
||||||
|
|
||||||
|
# connection con2;
|
||||||
|
# --error 0,ER_QUERY_INTERRUPTED
|
||||||
|
# reap;
|
||||||
|
# select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
#
|
||||||
|
# insert select
|
||||||
|
#
|
||||||
|
connection con1;
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t4;
|
||||||
|
--enable_warnings
|
||||||
|
create table t4 (a int, b int) engine=innodb;
|
||||||
|
insert into t4 values (3, 3);
|
||||||
|
begin; insert into t1 values (3, 3);
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
begin;
|
||||||
|
send insert into t1 select * from t4 for update;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--replace_result $ID ID
|
||||||
|
eval kill query $ID;
|
||||||
|
rollback;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
--error ER_QUERY_INTERRUPTED
|
||||||
|
reap;
|
||||||
|
rollback;
|
||||||
|
select * from t1 /* must be the same as before (1,1),(2,2) */;
|
||||||
|
|
||||||
|
drop table t4; # cleanup for the sub-case
|
||||||
|
|
||||||
|
###
|
||||||
|
## non-ta table case: killing must be recorded in binlog
|
||||||
|
###
|
||||||
delimiter |;
|
delimiter |;
|
||||||
create function bug27563()
|
create function bug27563(n int)
|
||||||
RETURNS int(11)
|
RETURNS int(11)
|
||||||
DETERMINISTIC
|
DETERMINISTIC
|
||||||
begin
|
begin
|
||||||
select get_lock("a", 10) into @a;
|
if n > 1 then
|
||||||
return 1;
|
select get_lock("a", 10) into @a;
|
||||||
|
end if;
|
||||||
|
return n;
|
||||||
end|
|
end|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
|
||||||
# the function is sensitive to killing requiring innodb though with wrong client error
|
#
|
||||||
# TO FIX in BUG#27565; TODO: remove --error 1105 afterwards
|
# update
|
||||||
delimiter |;
|
#
|
||||||
create function bug27565()
|
|
||||||
RETURNS int(11)
|
|
||||||
DETERMINISTIC
|
|
||||||
begin
|
|
||||||
select a from t1 where a=1 into @a for update;
|
|
||||||
return 1;
|
|
||||||
end|
|
|
||||||
delimiter ;|
|
|
||||||
|
|
||||||
|
delete from t2;
|
||||||
|
insert into t2 values (1,1), (2,2);
|
||||||
reset master;
|
reset master;
|
||||||
|
|
||||||
|
|
||||||
### ta table case: killing causes rollback
|
|
||||||
|
|
||||||
# A. autocommit ON
|
|
||||||
connection con1;
|
connection con1;
|
||||||
select get_lock("a", 20);
|
select get_lock("a", 20);
|
||||||
|
|
||||||
connection con2;
|
connection con2;
|
||||||
let $ID= `select connection_id()`;
|
let $ID= `select connection_id()`;
|
||||||
send insert into t1 values (bug27563(),1);
|
send update t2 set b=b + bug27563(b) order by a;
|
||||||
|
|
||||||
connection con1;
|
connection con1;
|
||||||
|
--replace_result $ID ID
|
||||||
eval kill query $ID;
|
eval kill query $ID;
|
||||||
|
|
||||||
connection con2;
|
connection con2;
|
||||||
# todo (re-record test): after bugs 27563,27565 got fixed affected rows will report zero
|
--error ER_QUERY_INTERRUPTED
|
||||||
--enable_info
|
|
||||||
# todo: remove 0 return after fixing Bug#27563
|
|
||||||
--error 0,ER_QUERY_INTERRUPTED
|
|
||||||
reap; ### pb: wrong error
|
|
||||||
--disable_info
|
|
||||||
###--replace_column 2 # 5 #
|
|
||||||
### show binlog events from 98 /* nothing in binlog unless Bug#27563 */;
|
|
||||||
show master status /* must be only FD event unless Bug#27563 */;
|
|
||||||
select count(*) from t1 /* must be zero unless Bug#27563 */;
|
|
||||||
|
|
||||||
# M. multi-statement-ta
|
|
||||||
connection con2;
|
|
||||||
let $ID= `select connection_id()`;
|
|
||||||
begin;
|
|
||||||
send insert into t1 values (bug27563(),1);
|
|
||||||
|
|
||||||
connection con1;
|
|
||||||
eval kill query $ID;
|
|
||||||
connection con2;
|
|
||||||
# todo (re-record test): after bugs 27563,27565 got fixed affected rows will report zero
|
|
||||||
--enable_info
|
|
||||||
# todo: remove 0 return after fixing Bug#27563
|
|
||||||
--error 0,ER_QUERY_INTERRUPTED
|
|
||||||
reap;
|
reap;
|
||||||
--disable_info
|
select * from t2 /* must be (1,2), (2,2) */;
|
||||||
select count(*) from t1 /* must be zero unless Bug#27563 */;
|
show master status /* must have the update event more to FD */;
|
||||||
commit;
|
|
||||||
|
|
||||||
|
# a proof the query is binlogged with an error
|
||||||
|
|
||||||
### non-ta table case: killing must be recorded in binlog
|
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
reset master;
|
eval select
|
||||||
|
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
connection con2;
|
is not null;
|
||||||
let $ID= `select connection_id()`;
|
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||||
send insert into t2 values (bug27563(),1);
|
let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`;
|
||||||
|
eval select $error_code /* must return 0 to mean the killed query is in */;
|
||||||
connection con1;
|
|
||||||
eval kill query $ID;
|
|
||||||
|
|
||||||
connection con2;
|
|
||||||
# todo: remove 0 return after fixing Bug#27563
|
|
||||||
--error 0,ER_QUERY_INTERRUPTED
|
|
||||||
reap;
|
|
||||||
select count(*) from t2 /* must be one */;
|
|
||||||
#show binlog events from 98 /* must have the insert on non-ta table */;
|
|
||||||
show master status /* must have the insert event more to FD */;
|
|
||||||
# the value of the error flag of KILLED_QUERY is tested further
|
|
||||||
|
|
||||||
|
# cleanup for the sub-case
|
||||||
connection con1;
|
connection con1;
|
||||||
select RELEASE_LOCK("a");
|
select RELEASE_LOCK("a");
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
|
|
||||||
### test with effective killing of SF()
|
#
|
||||||
|
# delete
|
||||||
|
#
|
||||||
|
|
||||||
delete from t1;
|
|
||||||
delete from t2;
|
delete from t2;
|
||||||
insert into t1 values (1,1);
|
insert into t2 values (1,1), (2,2);
|
||||||
insert into t2 values (1,1);
|
|
||||||
|
|
||||||
#
|
|
||||||
# Bug#27565
|
|
||||||
# test where KILL is propagated as error to the top level
|
|
||||||
# still another bug with the error message to the user
|
|
||||||
# todo: fix reexecute the result file after fixing
|
|
||||||
#
|
|
||||||
begin; update t1 set b=0 where a=1;
|
|
||||||
|
|
||||||
connection con2;
|
|
||||||
let $ID= `select connection_id()`;
|
|
||||||
send update t2 set b=bug27565()-1 where a=1;
|
|
||||||
|
|
||||||
connection con1;
|
|
||||||
eval kill query $ID;
|
|
||||||
commit;
|
|
||||||
|
|
||||||
connection con2;
|
|
||||||
# todo: fix Bug #27565 killed query of SF() is not reported correctly and
|
|
||||||
# remove 1105 (wrong)
|
|
||||||
#--error ER_QUERY_INTERRUPTED
|
|
||||||
--error 1105,ER_QUERY_INTERRUPTED
|
|
||||||
reap; ### pb: wrong error
|
|
||||||
select * from t1 /* must be: (1,0) */;
|
|
||||||
select * from t2 /* must be as before: (1,1) */;
|
|
||||||
|
|
||||||
## bug#22725 with effective and propagating killing
|
|
||||||
#
|
|
||||||
# top-level ta-table
|
|
||||||
connection con1;
|
|
||||||
delete from t3;
|
|
||||||
reset master;
|
reset master;
|
||||||
begin; update t1 set b=0 where a=1;
|
connection con1;
|
||||||
|
select get_lock("a", 20);
|
||||||
|
|
||||||
connection con2;
|
connection con2;
|
||||||
let $ID= `select connection_id()`;
|
let $ID= `select connection_id()`;
|
||||||
# the query won't perform completely since the function gets interrupted
|
send delete from t2 where a=1 or a=bug27563(2) order by a;
|
||||||
send insert into t3 values (0,0),(1,bug27565());
|
|
||||||
|
|
||||||
connection con1;
|
connection con1;
|
||||||
|
--replace_result $ID ID
|
||||||
eval kill query $ID;
|
eval kill query $ID;
|
||||||
rollback;
|
|
||||||
|
|
||||||
connection con2;
|
connection con2;
|
||||||
# todo: fix Bug #27565 killed query of SF() is not reported correctly and
|
--error ER_QUERY_INTERRUPTED
|
||||||
# remove 1105 (wrong)
|
reap;
|
||||||
#--error ER_QUERY_INTERRUPTED
|
select * from t2 /* must be (1,2), (2,2) */;
|
||||||
--error 1105,ER_QUERY_INTERRUPTED
|
show master status /* must have the update event more to FD */;
|
||||||
reap; ### pb: wrong error
|
|
||||||
select count(*) from t3 /* must be zero */;
|
|
||||||
show master status /* nothing in binlog */;
|
|
||||||
|
|
||||||
# top-level non-ta-table
|
# a proof the query is binlogged with an error
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
eval select
|
||||||
|
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null;
|
||||||
|
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||||
|
let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`;
|
||||||
|
eval select $error_code /* must return 0 to mean the killed query is in */;
|
||||||
|
|
||||||
|
# cleanup for the sub-case
|
||||||
connection con1;
|
connection con1;
|
||||||
delete from t2;
|
select RELEASE_LOCK("a");
|
||||||
reset master;
|
--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
begin; update t1 set b=0 where a=1;
|
|
||||||
|
|
||||||
connection con2;
|
#
|
||||||
let $ID= `select connection_id()`;
|
# load data - see simulation tests
|
||||||
# the query won't perform completely since the function gets intrurrupted
|
#
|
||||||
send insert into t2 values (0,0),(1,bug27565()) /* non-ta t2 */;
|
|
||||||
|
|
||||||
connection con1;
|
|
||||||
eval kill query $ID;
|
|
||||||
rollback;
|
|
||||||
|
|
||||||
connection con2;
|
# bug#27571 cleanup
|
||||||
# todo: fix Bug #27565 killed query of SF() is not reported correctly and
|
|
||||||
# remove 1105 (wrong)
|
|
||||||
#--error ER_QUERY_INTERRUPTED
|
|
||||||
--error 1105,ER_QUERY_INTERRUPTED
|
|
||||||
reap; ### pb: wrong error
|
|
||||||
|
|
||||||
select count(*) from t2 /* count must be one */;
|
|
||||||
show master status /* insert into non-ta must be in binlog */;
|
|
||||||
|
|
||||||
drop function bug27563;
|
drop function bug27563;
|
||||||
drop function bug27565;
|
|
||||||
}
|
|
||||||
|
|
||||||
system rm $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog ;
|
|
||||||
|
#
|
||||||
|
# common cleanup
|
||||||
|
#
|
||||||
|
|
||||||
drop table t1,t2,t3;
|
drop table t1,t2,t3;
|
||||||
|
|
||||||
|
--echo end of the tests
|
||||||
|
|
1
mysql-test/t/binlog_killed_bug27571-master.opt
Normal file
1
mysql-test/t/binlog_killed_bug27571-master.opt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--loose-debug=d,stop_after_row_loop_done
|
68
mysql-test/t/binlog_killed_bug27571.test
Normal file
68
mysql-test/t/binlog_killed_bug27571.test
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
--source include/have_log_bin.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# bug#27571 asynchronous setting mysql_`query`::error and Query_log_e::error_code
|
||||||
|
#
|
||||||
|
# Checking that if killing happens inbetween of the end of rows loop and
|
||||||
|
# recording into binlog that will not lead to recording any error incl
|
||||||
|
# the killed error.
|
||||||
|
#
|
||||||
|
|
||||||
|
connect (looser, localhost, root,,);
|
||||||
|
connect (killer, localhost, root,,);
|
||||||
|
|
||||||
|
create table t1 (a int auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
delete from t1;
|
||||||
|
insert into t1 values (1,1),(2,2);
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
connection looser;
|
||||||
|
let $ID= `select connection_id()`;
|
||||||
|
send update t1 set b=11 where a=2;
|
||||||
|
|
||||||
|
connection killer;
|
||||||
|
sleep 1; # let 1 second for the update to get to the sleeping point
|
||||||
|
--replace_result $ID ID
|
||||||
|
eval kill query $ID;
|
||||||
|
|
||||||
|
connection looser;
|
||||||
|
--error 0 # zero even though the query must be got killed while it was sleepin for 5 secs
|
||||||
|
reap;
|
||||||
|
|
||||||
|
#
|
||||||
|
# this is another possible artifact. The killed error was not caught
|
||||||
|
# as that is logical as killing was not effective:
|
||||||
|
# data are ok and well as binlog event is without killed error (further).
|
||||||
|
# The reason of the following `show error' is to prove that
|
||||||
|
# killing simulation was effective
|
||||||
|
#
|
||||||
|
show errors;
|
||||||
|
|
||||||
|
connection killer;
|
||||||
|
|
||||||
|
# nothing is rolled back
|
||||||
|
|
||||||
|
select * from t1 where a=2 /* must be 11 */;
|
||||||
|
|
||||||
|
# a proof the query is binlogged with an error
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
eval select
|
||||||
|
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null;
|
||||||
|
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||||
|
let $error_code= `select @a like "%#%error_code=0%"`;
|
||||||
|
|
||||||
|
eval select $error_code /* must return 1*/;
|
||||||
|
|
||||||
|
#
|
||||||
|
# cleanup
|
||||||
|
#
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
--echo end of the tests
|
1
mysql-test/t/binlog_killed_simulate-master.opt
Normal file
1
mysql-test/t/binlog_killed_simulate-master.opt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--loose-debug=d,simulate_kill_bug27571
|
65
mysql-test/t/binlog_killed_simulate.test
Normal file
65
mysql-test/t/binlog_killed_simulate.test
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#
|
||||||
|
# bug#27571 asynchronous setting mysql_$query()'s local error and
|
||||||
|
# Query_log_event::error_code
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1,t2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checking that killing upon successful row-loop does not affect binlogging
|
||||||
|
#
|
||||||
|
|
||||||
|
create table t1 (a int) engine=MyISAM;
|
||||||
|
insert into t1 set a=1;
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
update t1 set a=2 /* will be "killed" after work has been done */;
|
||||||
|
|
||||||
|
# a proof the query is binlogged with no error
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
eval select
|
||||||
|
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null;
|
||||||
|
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||||
|
let $error_code= `select @a like "%#%error_code=0%" /* must return 1 */`;
|
||||||
|
eval select $error_code /* must return 1 as query completed before got killed*/;
|
||||||
|
|
||||||
|
# cleanup for the sub-case
|
||||||
|
system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checking that killing inside of row-loop for LOAD DATA into
|
||||||
|
# non-transactional table affects binlogging
|
||||||
|
#
|
||||||
|
|
||||||
|
create table t2 (a int, b int) ENGINE=MyISAM;
|
||||||
|
reset master;
|
||||||
|
--error ER_QUERY_INTERRUPTED
|
||||||
|
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */;
|
||||||
|
|
||||||
|
|
||||||
|
# a proof the query is binlogged with an error
|
||||||
|
|
||||||
|
source include/show_binlog_events.inc;
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
eval select
|
||||||
|
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
|
||||||
|
is not null;
|
||||||
|
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
|
||||||
|
let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`;
|
||||||
|
eval select $error_code /* must return 0 to mean the killed query is in */;
|
||||||
|
|
||||||
|
# cleanup for the sub-case
|
||||||
|
system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog;
|
||||||
|
|
||||||
|
|
||||||
|
drop table t1,t2;
|
||||||
|
|
||||||
|
--echo end of the tests
|
|
@ -4994,12 +4994,13 @@ int Begin_load_query_log_event::get_create_or_append() const
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
Execute_load_query_log_event::
|
Execute_load_query_log_event::
|
||||||
Execute_load_query_log_event(THD* thd_arg, const char* query_arg,
|
Execute_load_query_log_event(THD* thd_arg, const char* query_arg,
|
||||||
ulong query_length_arg, uint fn_pos_start_arg,
|
ulong query_length_arg, uint fn_pos_start_arg,
|
||||||
uint fn_pos_end_arg,
|
uint fn_pos_end_arg,
|
||||||
enum_load_dup_handling dup_handling_arg,
|
enum_load_dup_handling dup_handling_arg,
|
||||||
bool using_trans, bool suppress_use):
|
bool using_trans, bool suppress_use,
|
||||||
|
THD::killed_state killed_err_arg):
|
||||||
Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
|
Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
|
||||||
suppress_use),
|
suppress_use, killed_err_arg),
|
||||||
file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
|
file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
|
||||||
fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
|
fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1619,10 +1619,12 @@ public:
|
||||||
|
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
Execute_load_query_log_event(THD* thd, const char* query_arg,
|
Execute_load_query_log_event(THD* thd, const char* query_arg,
|
||||||
ulong query_length, uint fn_pos_start_arg,
|
ulong query_length, uint fn_pos_start_arg,
|
||||||
uint fn_pos_end_arg,
|
uint fn_pos_end_arg,
|
||||||
enum_load_dup_handling dup_handling_arg,
|
enum_load_dup_handling dup_handling_arg,
|
||||||
bool using_trans, bool suppress_use);
|
bool using_trans, bool suppress_use,
|
||||||
|
THD::killed_state
|
||||||
|
killed_err_arg= THD::KILLED_NO_VALUE);
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
void pack_info(Protocol* protocol);
|
void pack_info(Protocol* protocol);
|
||||||
int exec_event(struct st_relay_log_info* rli);
|
int exec_event(struct st_relay_log_info* rli);
|
||||||
|
|
|
@ -38,6 +38,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||||
ha_rows deleted;
|
ha_rows deleted;
|
||||||
uint usable_index= MAX_KEY;
|
uint usable_index= MAX_KEY;
|
||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
|
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||||
DBUG_ENTER("mysql_delete");
|
DBUG_ENTER("mysql_delete");
|
||||||
|
|
||||||
if (open_and_lock_tables(thd, table_list))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
|
@ -280,8 +281,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||||
else
|
else
|
||||||
table->file->unlock_row(); // Row failed selection, release lock on it
|
table->file->unlock_row(); // Row failed selection, release lock on it
|
||||||
}
|
}
|
||||||
if (thd->killed && !error)
|
killed_status= thd->killed;
|
||||||
error= 1; // Aborted
|
error= (killed_status == THD::NOT_KILLED)? error : 1;
|
||||||
thd->proc_info="end";
|
thd->proc_info="end";
|
||||||
end_read_record(&info);
|
end_read_record(&info);
|
||||||
free_io_cache(table); // Will not do any harm
|
free_io_cache(table); // Will not do any harm
|
||||||
|
@ -326,7 +327,7 @@ cleanup:
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
transactional_table, FALSE);
|
transactional_table, FALSE, killed_status);
|
||||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
|
@ -729,7 +730,8 @@ void multi_delete::send_error(uint errcode,const char *err)
|
||||||
}
|
}
|
||||||
thd->transaction.all.modified_non_trans_table= true;
|
thd->transaction.all.modified_non_trans_table= true;
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
|
DBUG_ASSERT(!normal_tables || !deleted ||
|
||||||
|
thd->transaction.stmt.modified_non_trans_table);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,6 +819,7 @@ int multi_delete::do_deletes()
|
||||||
|
|
||||||
bool multi_delete::send_eof()
|
bool multi_delete::send_eof()
|
||||||
{
|
{
|
||||||
|
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||||
thd->proc_info="deleting from reference tables";
|
thd->proc_info="deleting from reference tables";
|
||||||
|
|
||||||
/* Does deletes for the last n - 1 tables, returns 0 if ok */
|
/* Does deletes for the last n - 1 tables, returns 0 if ok */
|
||||||
|
@ -824,7 +827,7 @@ bool multi_delete::send_eof()
|
||||||
|
|
||||||
/* compute a total error to know if something failed */
|
/* compute a total error to know if something failed */
|
||||||
local_error= local_error || error;
|
local_error= local_error || error;
|
||||||
|
killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
|
||||||
/* reset used flags */
|
/* reset used flags */
|
||||||
thd->proc_info="end";
|
thd->proc_info="end";
|
||||||
|
|
||||||
|
@ -836,7 +839,8 @@ bool multi_delete::send_eof()
|
||||||
{
|
{
|
||||||
query_cache_invalidate3(thd, delete_tables, 1);
|
query_cache_invalidate3(thd, delete_tables, 1);
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
|
DBUG_ASSERT(!normal_tables || !deleted ||
|
||||||
|
thd->transaction.stmt.modified_non_trans_table);
|
||||||
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
|
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
|
||||||
{
|
{
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
|
@ -844,7 +848,7 @@ bool multi_delete::send_eof()
|
||||||
if (local_error == 0)
|
if (local_error == 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
transactional_tables, FALSE);
|
transactional_tables, FALSE, killed_status);
|
||||||
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
||||||
local_error=1; // Log write failed: roll back the SQL statement
|
local_error=1; // Log write failed: roll back the SQL statement
|
||||||
}
|
}
|
||||||
|
|
|
@ -2936,6 +2936,7 @@ bool select_insert::send_eof()
|
||||||
{
|
{
|
||||||
int error, error2;
|
int error, error2;
|
||||||
bool changed, transactional_table= table->file->has_transactions();
|
bool changed, transactional_table= table->file->has_transactions();
|
||||||
|
THD::killed_state killed_status= thd->killed;
|
||||||
DBUG_ENTER("select_insert::send_eof");
|
DBUG_ENTER("select_insert::send_eof");
|
||||||
|
|
||||||
error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0;
|
error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0;
|
||||||
|
@ -2964,7 +2965,7 @@ bool select_insert::send_eof()
|
||||||
if (!error)
|
if (!error)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
transactional_table, FALSE);
|
transactional_table, FALSE, killed_status);
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
|
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
|
||||||
|
|
|
@ -85,7 +85,8 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
static bool write_execute_load_query_log_event(THD *thd,
|
static bool write_execute_load_query_log_event(THD *thd,
|
||||||
bool duplicates, bool ignore,
|
bool duplicates, bool ignore,
|
||||||
bool transactional_table);
|
bool transactional_table,
|
||||||
|
THD::killed_state killed_status);
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -135,6 +136,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||||
char *tdb= thd->db ? thd->db : db; // Result is never null
|
char *tdb= thd->db ? thd->db : db; // Result is never null
|
||||||
ulong skip_lines= ex->skip_lines;
|
ulong skip_lines= ex->skip_lines;
|
||||||
bool transactional_table;
|
bool transactional_table;
|
||||||
|
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||||
DBUG_ENTER("mysql_load");
|
DBUG_ENTER("mysql_load");
|
||||||
|
|
||||||
#ifdef EMBEDDED_LIBRARY
|
#ifdef EMBEDDED_LIBRARY
|
||||||
|
@ -404,7 +406,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||||
free_blobs(table); /* if pack_blob was used */
|
free_blobs(table); /* if pack_blob was used */
|
||||||
table->copy_blobs=0;
|
table->copy_blobs=0;
|
||||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||||
|
/*
|
||||||
|
simulated killing in the middle of per-row loop
|
||||||
|
must be effective for binlogging
|
||||||
|
*/
|
||||||
|
DBUG_EXECUTE_IF("simulate_kill_bug27571",
|
||||||
|
{
|
||||||
|
error=1;
|
||||||
|
thd->killed= THD::KILL_QUERY;
|
||||||
|
};);
|
||||||
|
killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
|
||||||
/*
|
/*
|
||||||
We must invalidate the table in query cache before binlog writing and
|
We must invalidate the table in query cache before binlog writing and
|
||||||
ha_autocommit_...
|
ha_autocommit_...
|
||||||
|
@ -446,7 +457,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||||
{
|
{
|
||||||
if (thd->transaction.stmt.modified_non_trans_table)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||||
ignore, transactional_table);
|
ignore, transactional_table,
|
||||||
|
killed_status);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Delete_file_log_event d(thd, db, transactional_table);
|
Delete_file_log_event d(thd, db, transactional_table);
|
||||||
|
@ -477,7 +489,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||||
read_info.end_io_cache();
|
read_info.end_io_cache();
|
||||||
if (lf_info.wrote_create_file)
|
if (lf_info.wrote_create_file)
|
||||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||||
ignore, transactional_table);
|
ignore, transactional_table,
|
||||||
|
killed_status);
|
||||||
}
|
}
|
||||||
#endif /*!EMBEDDED_LIBRARY*/
|
#endif /*!EMBEDDED_LIBRARY*/
|
||||||
if (transactional_table)
|
if (transactional_table)
|
||||||
|
@ -504,7 +517,8 @@ err:
|
||||||
/* Not a very useful function; just to avoid duplication of code */
|
/* Not a very useful function; just to avoid duplication of code */
|
||||||
static bool write_execute_load_query_log_event(THD *thd,
|
static bool write_execute_load_query_log_event(THD *thd,
|
||||||
bool duplicates, bool ignore,
|
bool duplicates, bool ignore,
|
||||||
bool transactional_table)
|
bool transactional_table,
|
||||||
|
THD::killed_state killed_err_arg)
|
||||||
{
|
{
|
||||||
Execute_load_query_log_event
|
Execute_load_query_log_event
|
||||||
e(thd, thd->query, thd->query_length,
|
e(thd, thd->query, thd->query_length,
|
||||||
|
@ -512,7 +526,7 @@ static bool write_execute_load_query_log_event(THD *thd,
|
||||||
(char*)thd->lex->fname_end - (char*)thd->query,
|
(char*)thd->lex->fname_end - (char*)thd->query,
|
||||||
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
|
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
|
||||||
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
|
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
|
||||||
transactional_table, FALSE);
|
transactional_table, FALSE, killed_err_arg);
|
||||||
return mysql_bin_log.write(&e);
|
return mysql_bin_log.write(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ int mysql_update(THD *thd,
|
||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
bool need_reopen;
|
bool need_reopen;
|
||||||
List<Item> all_fields;
|
List<Item> all_fields;
|
||||||
|
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||||
DBUG_ENTER("mysql_update");
|
DBUG_ENTER("mysql_update");
|
||||||
|
|
||||||
LINT_INIT(timestamp_query_id);
|
LINT_INIT(timestamp_query_id);
|
||||||
|
@ -519,43 +520,26 @@ int mysql_update(THD *thd,
|
||||||
table->file->unlock_row();
|
table->file->unlock_row();
|
||||||
thd->row_count++;
|
thd->row_count++;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Caching the killed status to pass as the arg to query event constuctor;
|
||||||
|
The cached value can not change whereas the killed status can
|
||||||
|
(externally) since this point and change of the latter won't affect
|
||||||
|
binlogging.
|
||||||
|
It's assumed that if an error was set in combination with an effective
|
||||||
|
killed status then the error is due to killing.
|
||||||
|
*/
|
||||||
|
killed_status= thd->killed; // get the status of the volatile
|
||||||
|
// simulated killing after the loop must be ineffective for binlogging
|
||||||
|
DBUG_EXECUTE_IF("simulate_kill_bug27571",
|
||||||
|
{
|
||||||
|
thd->killed= THD::KILL_QUERY;
|
||||||
|
};);
|
||||||
|
error= (killed_status == THD::NOT_KILLED)? error : 1;
|
||||||
|
|
||||||
|
|
||||||
if (!transactional_table && updated > 0)
|
if (!transactional_table && updated > 0)
|
||||||
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
todo bug#27571: to avoid asynchronization of `error' and
|
|
||||||
`error_code' of binlog event constructor
|
|
||||||
|
|
||||||
The concept, which is a bit different for insert(!), is to
|
|
||||||
replace `error' assignment with the following lines
|
|
||||||
|
|
||||||
killed_status= thd->killed; // get the status of the volatile
|
|
||||||
|
|
||||||
Notice: thd->killed is type of "state" whereas the lhs has
|
|
||||||
"status" the suffix which translates according to WordNet: a state
|
|
||||||
at a particular time - at the time of the end of per-row loop in
|
|
||||||
our case. Binlogging ops are conducted with the status.
|
|
||||||
|
|
||||||
error= (killed_status == THD::NOT_KILLED)? error : 1;
|
|
||||||
|
|
||||||
which applies to most mysql_$query functions.
|
|
||||||
Event's constructor will accept `killed_status' as an argument:
|
|
||||||
|
|
||||||
Query_log_event qinfo(..., killed_status);
|
|
||||||
|
|
||||||
thd->killed might be changed after killed_status had got cached and this
|
|
||||||
won't affect binlogging event but other effects remain.
|
|
||||||
|
|
||||||
Open issue: In a case the error happened not because of KILLED -
|
|
||||||
and then KILLED was caught later still within the loop - we shall
|
|
||||||
do something to avoid binlogging of incorrect ER_SERVER_SHUTDOWN
|
|
||||||
error_code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (thd->killed && !error)
|
|
||||||
error= 1; // Aborted
|
|
||||||
end_read_record(&info);
|
end_read_record(&info);
|
||||||
free_io_cache(table); // If ORDER BY
|
free_io_cache(table); // If ORDER BY
|
||||||
delete select;
|
delete select;
|
||||||
|
@ -587,7 +571,7 @@ int mysql_update(THD *thd,
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
transactional_table, FALSE);
|
transactional_table, FALSE, killed_status);
|
||||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||||
error=1; // Rollback update
|
error=1; // Rollback update
|
||||||
}
|
}
|
||||||
|
@ -1522,6 +1506,11 @@ void multi_update::send_error(uint errcode,const char *err)
|
||||||
*/
|
*/
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
THD::killed status might not have been set ON at time of an error
|
||||||
|
got caught and if happens later the killed error is written
|
||||||
|
into repl event.
|
||||||
|
*/
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
transactional_tables, FALSE);
|
transactional_tables, FALSE);
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
|
@ -1709,10 +1698,19 @@ err2:
|
||||||
bool multi_update::send_eof()
|
bool multi_update::send_eof()
|
||||||
{
|
{
|
||||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||||
|
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||||
thd->proc_info="updating reference tables";
|
thd->proc_info="updating reference tables";
|
||||||
|
|
||||||
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
/*
|
||||||
|
Does updates for the last n - 1 tables, returns 0 if ok;
|
||||||
|
error takes into account killed status gained in do_updates()
|
||||||
|
*/
|
||||||
int local_error = (table_count) ? do_updates(0) : 0;
|
int local_error = (table_count) ? do_updates(0) : 0;
|
||||||
|
/*
|
||||||
|
if local_error is not set ON until after do_updates() then
|
||||||
|
later carried out killing should not affect binlogging.
|
||||||
|
*/
|
||||||
|
killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
|
||||||
thd->proc_info= "end";
|
thd->proc_info= "end";
|
||||||
|
|
||||||
/* We must invalidate the query cache before binlog writing and
|
/* We must invalidate the query cache before binlog writing and
|
||||||
|
@ -1740,7 +1738,7 @@ bool multi_update::send_eof()
|
||||||
if (local_error == 0)
|
if (local_error == 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
transactional_tables, FALSE);
|
transactional_tables, FALSE, killed_status);
|
||||||
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
||||||
local_error= 1; // Rollback update
|
local_error= 1; // Rollback update
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue