mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 18:20:07 +01:00
Merge koti.dsl.inet.fi:/home/elkin/MySQL/TEAM/FIXES/5.0/bug27571_asyn_killed_flags
into koti.dsl.inet.fi:/home/elkin/MySQL/5.1-merge-bug27571
This commit is contained in:
commit
e65d20b5f4
19 changed files with 1226 additions and 165 deletions
144
mysql-test/r/rpl_slave_skip.result
Normal file
144
mysql-test/r/rpl_slave_skip.result
Normal file
|
@ -0,0 +1,144 @@
|
|||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
**** On Master ****
|
||||
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
|
||||
==== Skipping normal transactions ====
|
||||
**** On Slave ****
|
||||
STOP SLAVE;
|
||||
**** On Master ****
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, 'master');
|
||||
INSERT INTO t1 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, 'master');
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (4, 'master,slave');
|
||||
INSERT INTO t1 VALUES (5, 'master,slave');
|
||||
INSERT INTO t1 VALUES (6, 'master,slave');
|
||||
COMMIT;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
1 master
|
||||
2 master
|
||||
3 master
|
||||
4 master,slave
|
||||
5 master,slave
|
||||
6 master,slave
|
||||
**** On Slave ****
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
4 master,slave
|
||||
5 master,slave
|
||||
6 master,slave
|
||||
**** On Master ****
|
||||
DELETE FROM t1;
|
||||
==== Skipping two normal transactions ====
|
||||
**** On Slave ****
|
||||
STOP SLAVE;
|
||||
**** On Master ****
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, 'master');
|
||||
INSERT INTO t1 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, 'master');
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (4, 'master');
|
||||
INSERT INTO t1 VALUES (5, 'master');
|
||||
INSERT INTO t1 VALUES (6, 'master');
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (7, 'master,slave');
|
||||
INSERT INTO t1 VALUES (8, 'master,slave');
|
||||
INSERT INTO t1 VALUES (9, 'master,slave');
|
||||
COMMIT;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
1 master
|
||||
2 master
|
||||
3 master
|
||||
4 master
|
||||
5 master
|
||||
6 master
|
||||
7 master,slave
|
||||
8 master,slave
|
||||
9 master,slave
|
||||
**** On Slave ****
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
|
||||
START SLAVE;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
7 master,slave
|
||||
8 master,slave
|
||||
9 master,slave
|
||||
**** On Master ****
|
||||
DELETE FROM t1;
|
||||
==== Skipping without autocommit ====
|
||||
**** On Slave ****
|
||||
STOP SLAVE;
|
||||
**** On Master ****
|
||||
SET AUTOCOMMIT=0;
|
||||
INSERT INTO t1 VALUES (1, 'master');
|
||||
INSERT INTO t1 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, 'master');
|
||||
COMMIT;
|
||||
INSERT INTO t1 VALUES (4, 'master,slave');
|
||||
INSERT INTO t1 VALUES (5, 'master,slave');
|
||||
INSERT INTO t1 VALUES (6, 'master,slave');
|
||||
COMMIT;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
1 master
|
||||
2 master
|
||||
3 master
|
||||
4 master,slave
|
||||
5 master,slave
|
||||
6 master,slave
|
||||
**** On Slave ****
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
4 master,slave
|
||||
5 master,slave
|
||||
6 master,slave
|
||||
==== Rollback of transaction with non-transactional change ====
|
||||
**** On Master ****
|
||||
DELETE FROM t1;
|
||||
SET AUTOCOMMIT=1;
|
||||
**** On Slave ****
|
||||
STOP SLAVE;
|
||||
**** On Master ****
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, '');
|
||||
INSERT INTO t2 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, '');
|
||||
ROLLBACK;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (4, '');
|
||||
INSERT INTO t2 VALUES (5, 'master,slave');
|
||||
INSERT INTO t1 VALUES (6, '');
|
||||
ROLLBACK;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
a b
|
||||
2 master
|
||||
5 master,slave
|
||||
**** On Slave ****
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
a b
|
||||
5 master,slave
|
||||
==== Cleanup ====
|
||||
**** On Master ****
|
||||
DROP TABLE t1, t2;
|
|
@ -9,4 +9,110 @@ insert into t2 values (null, null), (null, get_lock("a", 10));
|
|||
select @result /* must be zero either way */;
|
||||
@result
|
||||
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;
|
||||
end of the tests
|
||||
|
|
|
@ -55,194 +55,239 @@ enable_result_log;
|
|||
|
||||
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
|
||||
# Bug#27563, Bug#27565, BUG#24971
|
||||
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
|
||||
|
||||
#
|
||||
# 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 |;
|
||||
create function bug27563()
|
||||
create function bug27563(n int)
|
||||
RETURNS int(11)
|
||||
DETERMINISTIC
|
||||
begin
|
||||
select get_lock("a", 10) into @a;
|
||||
return 1;
|
||||
if n > 1 then
|
||||
select get_lock("a", 10) into @a;
|
||||
end if;
|
||||
return n;
|
||||
end|
|
||||
delimiter ;|
|
||||
|
||||
# the function is sensitive to killing requiring innodb though with wrong client error
|
||||
# TO FIX in BUG#27565; TODO: remove --error 1105 afterwards
|
||||
delimiter |;
|
||||
create function bug27565()
|
||||
RETURNS int(11)
|
||||
DETERMINISTIC
|
||||
begin
|
||||
select a from t1 where a=1 into @a for update;
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
#
|
||||
# update
|
||||
#
|
||||
|
||||
delete from t2;
|
||||
insert into t2 values (1,1), (2,2);
|
||||
reset master;
|
||||
|
||||
|
||||
### ta table case: killing causes rollback
|
||||
|
||||
# A. autocommit ON
|
||||
connection con1;
|
||||
select get_lock("a", 20);
|
||||
|
||||
connection con2;
|
||||
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;
|
||||
--replace_result $ID ID
|
||||
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; ### 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
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
reap;
|
||||
--disable_info
|
||||
select count(*) from t1 /* must be zero unless Bug#27563 */;
|
||||
commit;
|
||||
select * from t2 /* must be (1,2), (2,2) */;
|
||||
show master status /* must have the update event more to FD */;
|
||||
|
||||
# a proof the query is binlogged with an error
|
||||
|
||||
### non-ta table case: killing must be recorded in binlog
|
||||
|
||||
reset master;
|
||||
|
||||
connection con2;
|
||||
let $ID= `select connection_id()`;
|
||||
send insert into t2 values (bug27563(),1);
|
||||
|
||||
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
|
||||
--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;
|
||||
select RELEASE_LOCK("a");
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||
|
||||
### test with effective killing of SF()
|
||||
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
insert into t1 values (1,1);
|
||||
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;
|
||||
begin; update t1 set b=0 where a=1;
|
||||
# delete
|
||||
#
|
||||
|
||||
connection con2;
|
||||
let $ID= `select connection_id()`;
|
||||
# the query won't perform completely since the function gets interrupted
|
||||
send insert into t3 values (0,0),(1,bug27565());
|
||||
|
||||
connection con1;
|
||||
eval kill query $ID;
|
||||
rollback;
|
||||
|
||||
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 count(*) from t3 /* must be zero */;
|
||||
show master status /* nothing in binlog */;
|
||||
|
||||
# top-level non-ta-table
|
||||
connection con1;
|
||||
delete from t2;
|
||||
insert into t2 values (1,1), (2,2);
|
||||
reset master;
|
||||
begin; update t1 set b=0 where a=1;
|
||||
connection con1;
|
||||
select get_lock("a", 20);
|
||||
|
||||
connection con2;
|
||||
let $ID= `select connection_id()`;
|
||||
# the query won't perform completely since the function gets intrurrupted
|
||||
send insert into t2 values (0,0),(1,bug27565()) /* non-ta t2 */;
|
||||
send delete from t2 where a=1 or a=bug27563(2) order by a;
|
||||
|
||||
connection con1;
|
||||
--replace_result $ID ID
|
||||
eval kill query $ID;
|
||||
rollback;
|
||||
|
||||
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
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
reap;
|
||||
select * from t2 /* must be (1,2), (2,2) */;
|
||||
show master status /* must have the update event more to FD */;
|
||||
|
||||
select count(*) from t2 /* count must be one */;
|
||||
show master status /* insert into non-ta must be in binlog */;
|
||||
# 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;
|
||||
select RELEASE_LOCK("a");
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
|
||||
|
||||
#
|
||||
# load data - see simulation tests
|
||||
#
|
||||
|
||||
|
||||
# bug#27571 cleanup
|
||||
|
||||
drop function bug27563;
|
||||
drop function bug27565;
|
||||
}
|
||||
|
||||
system rm $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog ;
|
||||
|
||||
#
|
||||
# common cleanup
|
||||
#
|
||||
|
||||
drop table t1,t2,t3;
|
||||
|
||||
--echo end of the tests
|
||||
|
|
|
@ -201,6 +201,10 @@ sync_slave_with_master;
|
|||
connection slave;
|
||||
SELECT 'slave', a FROM t1 ORDER BY a;
|
||||
|
||||
#
|
||||
# cleanup
|
||||
#
|
||||
|
||||
connection master;
|
||||
drop table t1;
|
||||
drop function f1;
|
||||
|
@ -208,4 +212,50 @@ drop function f2;
|
|||
drop procedure p1;
|
||||
sync_slave_with_master;
|
||||
|
||||
#
|
||||
# bug#26199 Replication Failure on Slave when using stored procs
|
||||
# with bit-type parameters
|
||||
|
||||
connection master;
|
||||
|
||||
create table t2 (b BIT(7));
|
||||
delimiter //;
|
||||
create procedure sp_bug26199(bitvalue BIT(7))
|
||||
begin
|
||||
insert into t2 set b = bitvalue;
|
||||
end //
|
||||
|
||||
create function sf_bug26199(b BIT(7)) returns int
|
||||
begin
|
||||
insert into t2 values(b);
|
||||
return 0;
|
||||
end//
|
||||
|
||||
DELIMITER ;//
|
||||
|
||||
|
||||
|
||||
call sp_bug26199(b'1110');
|
||||
call sp_bug26199('\0');
|
||||
select sf_bug26199(b'1111111');
|
||||
select sf_bug26199(b'101111111');
|
||||
select sf_bug26199('\'');
|
||||
select hex(b) from t2;
|
||||
|
||||
sync_slave_with_master;
|
||||
#connection slave;
|
||||
select hex(b) from t2;
|
||||
|
||||
#
|
||||
# cleanup bug#26199
|
||||
#
|
||||
connection master;
|
||||
drop table t2;
|
||||
drop procedure sp_bug26199;
|
||||
drop function sf_bug26199;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
SET GLOBAL log_bin_trust_function_creators = 0;
|
||||
|
||||
--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
|
1
mysql-test/t/rpl_slave_skip-slave.opt
Normal file
1
mysql-test/t/rpl_slave_skip-slave.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--innodb
|
203
mysql-test/t/rpl_slave_skip.test
Normal file
203
mysql-test/t/rpl_slave_skip.test
Normal file
|
@ -0,0 +1,203 @@
|
|||
source include/have_innodb.inc;
|
||||
source include/master-slave.inc;
|
||||
|
||||
# This test is for checking that the use of SQL_SLAVE_SKIP_COUNTER
|
||||
# behaves as expected, i.e., that it is guaranteed to skip an entire
|
||||
# group and not start executing in the middle of a transaction.
|
||||
|
||||
# We are checking the correct behaviour when using both a
|
||||
# transactional and non-transactional table. The non-transactional
|
||||
# table comes into play when rolling back a transaction containing a
|
||||
# write to this table. In that case, the transaction should still be
|
||||
# written to the binary log, and the slave will apply it and then roll
|
||||
# it back to get the non-transactional change into the table.
|
||||
|
||||
--echo **** On Master ****
|
||||
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
|
||||
|
||||
--echo ==== Skipping normal transactions ====
|
||||
|
||||
--echo **** On Slave ****
|
||||
sync_slave_with_master;
|
||||
STOP SLAVE;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, 'master');
|
||||
INSERT INTO t1 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, 'master');
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (4, 'master,slave');
|
||||
INSERT INTO t1 VALUES (5, 'master,slave');
|
||||
INSERT INTO t1 VALUES (6, 'master,slave');
|
||||
COMMIT;
|
||||
|
||||
save_master_pos;
|
||||
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
# This will skip a begin event and the first INSERT of the
|
||||
# transaction, and it should keep skipping until it has reached the
|
||||
# transaction terminator.
|
||||
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
source include/wait_for_slave_to_start.inc;
|
||||
sync_with_master;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
DELETE FROM t1;
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo ==== Skipping two normal transactions ====
|
||||
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
STOP SLAVE;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, 'master');
|
||||
INSERT INTO t1 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, 'master');
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (4, 'master');
|
||||
INSERT INTO t1 VALUES (5, 'master');
|
||||
INSERT INTO t1 VALUES (6, 'master');
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (7, 'master,slave');
|
||||
INSERT INTO t1 VALUES (8, 'master,slave');
|
||||
INSERT INTO t1 VALUES (9, 'master,slave');
|
||||
COMMIT;
|
||||
|
||||
save_master_pos;
|
||||
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
# This will skip a begin event and the first INSERT of the
|
||||
# transaction, and it should keep skipping until it has reached the
|
||||
# transaction terminator.
|
||||
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
|
||||
START SLAVE;
|
||||
source include/wait_for_slave_to_start.inc;
|
||||
sync_with_master;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
DELETE FROM t1;
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo ==== Skipping without autocommit ====
|
||||
|
||||
# Testing without using autocommit instead. It should still write a
|
||||
# BEGIN event, so the behaviour should be the same
|
||||
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
STOP SLAVE;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
SET AUTOCOMMIT=0;
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'master');
|
||||
INSERT INTO t1 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, 'master');
|
||||
COMMIT;
|
||||
|
||||
INSERT INTO t1 VALUES (4, 'master,slave');
|
||||
INSERT INTO t1 VALUES (5, 'master,slave');
|
||||
INSERT INTO t1 VALUES (6, 'master,slave');
|
||||
COMMIT;
|
||||
|
||||
save_master_pos;
|
||||
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
# This will skip a begin event and the first INSERT of the
|
||||
# transaction, and it should keep skipping until it has reached the
|
||||
# transaction terminator.
|
||||
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
source include/wait_for_slave_to_start.inc;
|
||||
sync_with_master;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
# Testing with a non-transactional table in the transaction. This will
|
||||
# log a ROLLBACK as a transaction terminator, which is a normal Query
|
||||
# log event.
|
||||
|
||||
--echo ==== Rollback of transaction with non-transactional change ====
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
DELETE FROM t1;
|
||||
SET AUTOCOMMIT=1;
|
||||
|
||||
--echo **** On Slave ****
|
||||
sync_slave_with_master;
|
||||
STOP SLAVE;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
disable_warnings;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, '');
|
||||
INSERT INTO t2 VALUES (2, 'master');
|
||||
INSERT INTO t1 VALUES (3, '');
|
||||
ROLLBACK;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (4, '');
|
||||
INSERT INTO t2 VALUES (5, 'master,slave');
|
||||
INSERT INTO t1 VALUES (6, '');
|
||||
ROLLBACK;
|
||||
enable_warnings;
|
||||
|
||||
save_master_pos;
|
||||
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
source include/wait_for_slave_to_start.inc;
|
||||
sync_with_master;
|
||||
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
|
||||
--echo ==== Cleanup ====
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
DROP TABLE t1, t2;
|
||||
sync_slave_with_master;
|
|
@ -4410,7 +4410,7 @@ Item_func_regex::regcomp(bool send_error)
|
|||
res= &conv;
|
||||
}
|
||||
|
||||
if ((error= my_regcomp(&preg, res->c_ptr(),
|
||||
if ((error= my_regcomp(&preg, res->c_ptr_safe(),
|
||||
regex_lib_flags, regex_lib_charset)))
|
||||
{
|
||||
if (send_error)
|
||||
|
|
|
@ -5472,12 +5472,13 @@ Begin_load_query_log_event::do_shall_skip(Relay_log_info *rli)
|
|||
#ifndef MYSQL_CLIENT
|
||||
Execute_load_query_log_event::
|
||||
Execute_load_query_log_event(THD *thd_arg, const char* query_arg,
|
||||
ulong query_length_arg, uint fn_pos_start_arg,
|
||||
uint fn_pos_end_arg,
|
||||
enum_load_dup_handling dup_handling_arg,
|
||||
bool using_trans, bool suppress_use):
|
||||
ulong query_length_arg, uint fn_pos_start_arg,
|
||||
uint fn_pos_end_arg,
|
||||
enum_load_dup_handling dup_handling_arg,
|
||||
bool using_trans, bool suppress_use,
|
||||
THD::killed_state killed_err_arg):
|
||||
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),
|
||||
fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
|
||||
{
|
||||
|
|
|
@ -2744,10 +2744,12 @@ public:
|
|||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Execute_load_query_log_event(THD* thd, const char* query_arg,
|
||||
ulong query_length, uint fn_pos_start_arg,
|
||||
uint fn_pos_end_arg,
|
||||
enum_load_dup_handling dup_handling_arg,
|
||||
bool using_trans, bool suppress_use);
|
||||
ulong query_length, uint fn_pos_start_arg,
|
||||
uint fn_pos_end_arg,
|
||||
enum_load_dup_handling dup_handling_arg,
|
||||
bool using_trans, bool suppress_use,
|
||||
THD::killed_state
|
||||
killed_err_arg= THD::KILLED_NO_VALUE);
|
||||
#ifdef HAVE_REPLICATION
|
||||
void pack_info(Protocol* protocol);
|
||||
#endif /* HAVE_REPLICATION */
|
||||
|
|
154
sql/slave.cc
154
sql/slave.cc
|
@ -1807,6 +1807,58 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
|
|||
/*
|
||||
*/
|
||||
|
||||
<<<<<<< gca sql/slave.cc 1.241.1.61
|
||||
DBUG_PRINT("info",("type_code=%d, server_id=%d",type_code,ev->server_id));
|
||||
|
||||
if ((ev->server_id == (uint32) ::server_id &&
|
||||
!replicate_same_server_id &&
|
||||
type_code != FORMAT_DESCRIPTION_EVENT) ||
|
||||
(rli->slave_skip_counter &&
|
||||
type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
|
||||
type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
|
||||
{
|
||||
DBUG_PRINT("info", ("event skipped"));
|
||||
if (thd->options & OPTION_BEGIN)
|
||||
rli->inc_event_relay_log_pos();
|
||||
else
|
||||
{
|
||||
rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
|
||||
type_code == STOP_EVENT ||
|
||||
type_code == FORMAT_DESCRIPTION_EVENT) ?
|
||||
LL(0) : ev->log_pos,
|
||||
1/* skip lock*/);
|
||||
flush_relay_log_info(rli);
|
||||
}
|
||||
|
||||
/*
|
||||
Protect against common user error of setting the counter to 1
|
||||
instead of 2 while recovering from an insert which used auto_increment,
|
||||
rand or user var.
|
||||
*/
|
||||
if (rli->slave_skip_counter &&
|
||||
!((type_code == INTVAR_EVENT ||
|
||||
type_code == RAND_EVENT ||
|
||||
type_code == USER_VAR_EVENT) &&
|
||||
rli->slave_skip_counter == 1) &&
|
||||
/*
|
||||
The events from ourselves which have something to do with the relay
|
||||
log itself must be skipped, true, but they mustn't decrement
|
||||
rli->slave_skip_counter, because the user is supposed to not see
|
||||
these events (they are not in the master's binlog) and if we
|
||||
decremented, START SLAVE would for example decrement when it sees
|
||||
the Rotate, so the event which the user probably wanted to skip
|
||||
would not be skipped.
|
||||
*/
|
||||
!(ev->server_id == (uint32) ::server_id &&
|
||||
(type_code == ROTATE_EVENT || type_code == STOP_EVENT ||
|
||||
type_code == START_EVENT_V3 || type_code == FORMAT_DESCRIPTION_EVENT)))
|
||||
--rli->slave_skip_counter;
|
||||
pthread_mutex_unlock(&rli->data_lock);
|
||||
delete ev;
|
||||
return 0; // avoid infinite update loops
|
||||
}
|
||||
pthread_mutex_unlock(&rli->data_lock);
|
||||
<<<<<<< local sql/slave.cc 1.321
|
||||
DBUG_PRINT("exec_event",("%s(type_code: %d; server_id: %d)",
|
||||
ev->get_type_str(), type_code, ev->server_id));
|
||||
DBUG_PRINT("info", ("thd->options: %s%s; rli->last_event_start_time: %lu",
|
||||
|
@ -1839,6 +1891,108 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
|
|||
log (remember that now the relay log starts with its Format_desc,
|
||||
has a Rotate etc).
|
||||
*/
|
||||
<<<<<<< remote sql/slave.cc 1.241.1.62
|
||||
DBUG_PRINT("info",("type_code: %d; server_id: %d; slave_skip_counter: %d",
|
||||
type_code, ev->server_id, rli->slave_skip_counter));
|
||||
|
||||
/*
|
||||
If the slave skip counter is positive, we still need to set the
|
||||
OPTION_BEGIN flag correctly and not skip the log events that
|
||||
start or end a transaction. If we do this, the slave will not
|
||||
notice that it is inside a transaction, and happily start
|
||||
executing from inside the transaction.
|
||||
|
||||
Note that the code block below is strictly 5.0.
|
||||
*/
|
||||
#if MYSQL_VERSION_ID < 50100
|
||||
if (unlikely(rli->slave_skip_counter > 0))
|
||||
{
|
||||
switch (type_code)
|
||||
{
|
||||
case QUERY_EVENT:
|
||||
{
|
||||
Query_log_event* const qev= (Query_log_event*) ev;
|
||||
DBUG_PRINT("info", ("QUERY_EVENT { query: '%s', q_len: %u }",
|
||||
qev->query, qev->q_len));
|
||||
if (memcmp("BEGIN", qev->query, qev->q_len+1) == 0)
|
||||
thd->options|= OPTION_BEGIN;
|
||||
else if (memcmp("COMMIT", qev->query, qev->q_len+1) == 0 ||
|
||||
memcmp("ROLLBACK", qev->query, qev->q_len+1) == 0)
|
||||
thd->options&= ~OPTION_BEGIN;
|
||||
}
|
||||
break;
|
||||
|
||||
case XID_EVENT:
|
||||
DBUG_PRINT("info", ("XID_EVENT"));
|
||||
thd->options&= ~OPTION_BEGIN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ev->server_id == (uint32) ::server_id &&
|
||||
!replicate_same_server_id &&
|
||||
type_code != FORMAT_DESCRIPTION_EVENT) ||
|
||||
(rli->slave_skip_counter &&
|
||||
type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
|
||||
type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
|
||||
{
|
||||
DBUG_PRINT("info", ("event skipped"));
|
||||
if (thd->options & OPTION_BEGIN)
|
||||
rli->inc_event_relay_log_pos();
|
||||
else
|
||||
{
|
||||
rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
|
||||
type_code == STOP_EVENT ||
|
||||
type_code == FORMAT_DESCRIPTION_EVENT) ?
|
||||
LL(0) : ev->log_pos,
|
||||
1/* skip lock*/);
|
||||
flush_relay_log_info(rli);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("thd->options: %s",
|
||||
(thd->options & OPTION_BEGIN) ? "OPTION_BEGIN" : ""))
|
||||
|
||||
/*
|
||||
Protect against common user error of setting the counter to 1
|
||||
instead of 2 while recovering from an insert which used auto_increment,
|
||||
rand or user var.
|
||||
*/
|
||||
if (rli->slave_skip_counter &&
|
||||
!((type_code == INTVAR_EVENT ||
|
||||
type_code == RAND_EVENT ||
|
||||
type_code == USER_VAR_EVENT) &&
|
||||
rli->slave_skip_counter == 1) &&
|
||||
#if MYSQL_VERSION_ID < 50100
|
||||
/*
|
||||
Decrease the slave skip counter only if we are not inside
|
||||
a transaction or the slave skip counter is more than
|
||||
1. The slave skip counter will be decreased from 1 to 0
|
||||
when reaching the final ROLLBACK, COMMIT, or XID_EVENT.
|
||||
*/
|
||||
(!(thd->options & OPTION_BEGIN) || rli->slave_skip_counter > 1) &&
|
||||
#endif
|
||||
/*
|
||||
The events from ourselves which have something to do with the relay
|
||||
log itself must be skipped, true, but they mustn't decrement
|
||||
rli->slave_skip_counter, because the user is supposed to not see
|
||||
these events (they are not in the master's binlog) and if we
|
||||
decremented, START SLAVE would for example decrement when it sees
|
||||
the Rotate, so the event which the user probably wanted to skip
|
||||
would not be skipped.
|
||||
*/
|
||||
!(ev->server_id == (uint32) ::server_id &&
|
||||
(type_code == ROTATE_EVENT ||
|
||||
type_code == STOP_EVENT ||
|
||||
type_code == START_EVENT_V3 ||
|
||||
type_code == FORMAT_DESCRIPTION_EVENT)))
|
||||
--rli->slave_skip_counter;
|
||||
pthread_mutex_unlock(&rli->data_lock);
|
||||
delete ev;
|
||||
return 0; // avoid infinite update loops
|
||||
}
|
||||
pthread_mutex_unlock(&rli->data_lock);
|
||||
>>>>>>>
|
||||
|
||||
thd->server_id = ev->server_id; // use the original server id for logging
|
||||
thd->set_time(); // time the query
|
||||
|
|
|
@ -102,8 +102,9 @@ sp_get_item_value(THD *thd, Item *item, String *str)
|
|||
case REAL_RESULT:
|
||||
case INT_RESULT:
|
||||
case DECIMAL_RESULT:
|
||||
return item->val_str(str);
|
||||
|
||||
if (item->field_type() != MYSQL_TYPE_BIT)
|
||||
return item->val_str(str);
|
||||
else {/* Bit type is handled as binary string */}
|
||||
case STRING_RESULT:
|
||||
{
|
||||
String *result= item->val_str(str);
|
||||
|
|
|
@ -38,6 +38,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||
ha_rows deleted= 0;
|
||||
uint usable_index= MAX_KEY;
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||
DBUG_ENTER("mysql_delete");
|
||||
|
||||
if (open_and_lock_tables(thd, table_list))
|
||||
|
@ -300,8 +301,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||
else
|
||||
table->file->unlock_row(); // Row failed selection, release lock on it
|
||||
}
|
||||
if (thd->killed && !error)
|
||||
error= 1; // Aborted
|
||||
killed_status= thd->killed;
|
||||
error= (killed_status == THD::NOT_KILLED)? error : 1;
|
||||
if (will_batch && (loc_error= table->file->end_bulk_delete()))
|
||||
{
|
||||
if (error != 1)
|
||||
|
@ -351,6 +352,11 @@ cleanup:
|
|||
{
|
||||
if (error < 0)
|
||||
thd->clear_error();
|
||||
<<<<<<< gca sql/sql_delete.cc 1.144.1.57
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_table, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
<<<<<<< local sql/sql_delete.cc 1.230
|
||||
|
||||
/*
|
||||
[binlog]: If 'handler::delete_all_rows()' was called and the
|
||||
|
@ -364,6 +370,11 @@ cleanup:
|
|||
|
||||
if (log_result && transactional_table)
|
||||
{
|
||||
<<<<<<< remote sql/sql_delete.cc 1.144.1.58
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_table, FALSE, killed_status);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
>>>>>>>
|
||||
error=1;
|
||||
}
|
||||
}
|
||||
|
@ -764,7 +775,8 @@ void multi_delete::send_error(uint errcode,const char *err)
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -862,6 +874,7 @@ int multi_delete::do_deletes()
|
|||
|
||||
bool multi_delete::send_eof()
|
||||
{
|
||||
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||
thd->proc_info="deleting from reference tables";
|
||||
|
||||
/* Does deletes for the last n - 1 tables, returns 0 if ok */
|
||||
|
@ -869,7 +882,7 @@ bool multi_delete::send_eof()
|
|||
|
||||
/* compute a total error to know if something failed */
|
||||
local_error= local_error || error;
|
||||
|
||||
killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
|
||||
/* reset used flags */
|
||||
thd->proc_info="end";
|
||||
|
||||
|
@ -881,18 +894,29 @@ bool multi_delete::send_eof()
|
|||
{
|
||||
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 (mysql_bin_log.is_open())
|
||||
{
|
||||
if (local_error == 0)
|
||||
thd->clear_error();
|
||||
<<<<<<< gca sql/sql_delete.cc 1.144.1.57
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_tables, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
||||
<<<<<<< local sql/sql_delete.cc 1.230
|
||||
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||
thd->query, thd->query_length,
|
||||
transactional_tables, FALSE) &&
|
||||
!normal_tables)
|
||||
{
|
||||
<<<<<<< remote sql/sql_delete.cc 1.144.1.58
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_tables, FALSE, killed_status);
|
||||
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
||||
>>>>>>>
|
||||
local_error=1; // Log write failed: roll back the SQL statement
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3084,10 +3084,19 @@ void select_insert::send_error(uint errcode,const char *err)
|
|||
|
||||
bool select_insert::send_eof()
|
||||
{
|
||||
<<<<<<< gca sql/sql_insert.cc 1.146.1.105
|
||||
int error, error2;
|
||||
bool changed, transactional_table= table->file->has_transactions();
|
||||
<<<<<<< local sql/sql_insert.cc 1.300
|
||||
int error;
|
||||
bool const trans_table= table->file->has_transactions();
|
||||
ulonglong id;
|
||||
bool changed;
|
||||
<<<<<<< remote sql/sql_insert.cc 1.146.1.106
|
||||
int error, error2;
|
||||
bool changed, transactional_table= table->file->has_transactions();
|
||||
THD::killed_state killed_status= thd->killed;
|
||||
>>>>>>>
|
||||
DBUG_ENTER("select_insert::send_eof");
|
||||
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
|
||||
trans_table, table->file->table_type()));
|
||||
|
@ -3120,6 +3129,14 @@ bool select_insert::send_eof()
|
|||
{
|
||||
if (!error)
|
||||
thd->clear_error();
|
||||
<<<<<<< gca sql/sql_insert.cc 1.146.1.105
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_table, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
|
||||
error=error2;
|
||||
<<<<<<< local sql/sql_insert.cc 1.300
|
||||
thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||
thd->query, thd->query_length,
|
||||
trans_table, FALSE);
|
||||
|
@ -3138,6 +3155,14 @@ bool select_insert::send_eof()
|
|||
}
|
||||
table->file->ha_release_auto_increment();
|
||||
|
||||
<<<<<<< remote sql/sql_insert.cc 1.146.1.106
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_table, FALSE, killed_status);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
|
||||
error=error2;
|
||||
>>>>>>>
|
||||
if (error)
|
||||
{
|
||||
table->file->print_error(error,MYF(0));
|
||||
|
|
|
@ -85,7 +85,8 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||
#ifndef EMBEDDED_LIBRARY
|
||||
static bool write_execute_load_query_log_event(THD *thd,
|
||||
bool duplicates, bool ignore,
|
||||
bool transactional_table);
|
||||
bool transactional_table,
|
||||
THD::killed_state killed_status);
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
|
||||
/*
|
||||
|
@ -134,6 +135,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
char *tdb= thd->db ? thd->db : db; // Result is never null
|
||||
ulong skip_lines= ex->skip_lines;
|
||||
bool transactional_table;
|
||||
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||
DBUG_ENTER("mysql_load");
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
|
@ -403,7 +405,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
free_blobs(table); /* if pack_blob was used */
|
||||
table->copy_blobs=0;
|
||||
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
|
||||
ha_autocommit_...
|
||||
|
@ -419,6 +430,12 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
{
|
||||
<<<<<<< gca sql/sql_load.cc 1.78.1.39
|
||||
if (thd->transaction.stmt.modified_non_trans_table)
|
||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||
ignore, transactional_table);
|
||||
else
|
||||
<<<<<<< local sql/sql_load.cc 1.131
|
||||
/*
|
||||
Make sure last block (the one which caused the error) gets
|
||||
logged. This is needed because otherwise after write of (to
|
||||
|
@ -444,6 +461,13 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
read_info.end_io_cache();
|
||||
/* If the file was not empty, wrote_create_file is true */
|
||||
if (lf_info.wrote_create_file)
|
||||
<<<<<<< remote sql/sql_load.cc 1.78.1.40
|
||||
if (thd->transaction.stmt.modified_non_trans_table)
|
||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||
ignore, transactional_table,
|
||||
killed_status);
|
||||
else
|
||||
>>>>>>>
|
||||
{
|
||||
if (thd->transaction.stmt.modified_non_trans_table)
|
||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||
|
@ -473,6 +497,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
/*
|
||||
<<<<<<< gca sql/sql_load.cc 1.78.1.39
|
||||
As already explained above, we need to call end_io_cache() or the last
|
||||
block will be logged only after Execute_load_query_log_event (which is
|
||||
wrong), when read_info is destroyed.
|
||||
*/
|
||||
read_info.end_io_cache();
|
||||
if (lf_info.wrote_create_file)
|
||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||
ignore, transactional_table);
|
||||
<<<<<<< local sql/sql_load.cc 1.131
|
||||
We need to do the job that is normally done inside
|
||||
binlog_query() here, which is to ensure that the pending event
|
||||
is written before tables are unlocked and before any other
|
||||
|
@ -496,6 +530,17 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
ignore, transactional_table);
|
||||
}
|
||||
}
|
||||
<<<<<<< remote sql/sql_load.cc 1.78.1.40
|
||||
As already explained above, we need to call end_io_cache() or the last
|
||||
block will be logged only after Execute_load_query_log_event (which is
|
||||
wrong), when read_info is destroyed.
|
||||
*/
|
||||
read_info.end_io_cache();
|
||||
if (lf_info.wrote_create_file)
|
||||
write_execute_load_query_log_event(thd, handle_duplicates,
|
||||
ignore, transactional_table,
|
||||
killed_status);
|
||||
>>>>>>>
|
||||
}
|
||||
#endif /*!EMBEDDED_LIBRARY*/
|
||||
if (transactional_table)
|
||||
|
@ -523,7 +568,8 @@ err:
|
|||
/* Not a very useful function; just to avoid duplication of code */
|
||||
static bool write_execute_load_query_log_event(THD *thd,
|
||||
bool duplicates, bool ignore,
|
||||
bool transactional_table)
|
||||
bool transactional_table,
|
||||
THD::killed_state killed_err_arg)
|
||||
{
|
||||
Execute_load_query_log_event
|
||||
e(thd, thd->query, thd->query_length,
|
||||
|
@ -531,8 +577,14 @@ static bool write_execute_load_query_log_event(THD *thd,
|
|||
(char*)thd->lex->fname_end - (char*)thd->query,
|
||||
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
|
||||
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
|
||||
<<<<<<< gca sql/sql_load.cc 1.78.1.39
|
||||
transactional_table, FALSE);
|
||||
<<<<<<< local sql/sql_load.cc 1.131
|
||||
transactional_table, FALSE);
|
||||
e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
|
||||
<<<<<<< remote sql/sql_load.cc 1.78.1.40
|
||||
transactional_table, FALSE, killed_err_arg);
|
||||
>>>>>>>
|
||||
return mysql_bin_log.write(&e);
|
||||
}
|
||||
|
||||
|
|
|
@ -200,9 +200,18 @@ int mysql_update(THD *thd,
|
|||
SQL_SELECT *select;
|
||||
READ_RECORD info;
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
bool need_reopen;
|
||||
List<Item> all_fields;
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
bool need_reopen;
|
||||
ulonglong id;
|
||||
List<Item> all_fields;
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
bool need_reopen;
|
||||
List<Item> all_fields;
|
||||
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||
>>>>>>>
|
||||
DBUG_ENTER("mysql_update");
|
||||
|
||||
for ( ; ; )
|
||||
|
@ -713,11 +722,66 @@ int mysql_update(THD *thd,
|
|||
table->file->unlock_row();
|
||||
thd->row_count++;
|
||||
}
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
dup_key_found= 0;
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
/*
|
||||
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)
|
||||
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
|
||||
/*
|
||||
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
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
|
||||
/*
|
||||
todo bug#27571: to avoid asynchronization of `error' and
|
||||
|
@ -774,6 +838,8 @@ int mysql_update(THD *thd,
|
|||
if (will_batch)
|
||||
table->file->end_bulk_update();
|
||||
table->file->try_semi_consistent_read(0);
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
>>>>>>>
|
||||
end_read_record(&info);
|
||||
delete select;
|
||||
thd->proc_info= "end";
|
||||
|
@ -803,6 +869,12 @@ int mysql_update(THD *thd,
|
|||
{
|
||||
if (error < 0)
|
||||
thd->clear_error();
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_table, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
error=1; // Rollback update
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||
thd->query, thd->query_length,
|
||||
transactional_table, FALSE) &&
|
||||
|
@ -810,6 +882,12 @@ int mysql_update(THD *thd,
|
|||
{
|
||||
error=1; // Rollback update
|
||||
}
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_table, FALSE, killed_status);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
error=1; // Rollback update
|
||||
>>>>>>>
|
||||
}
|
||||
if (thd->transaction.stmt.modified_non_trans_table)
|
||||
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||
|
@ -1751,9 +1829,24 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||
*/
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_tables, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||
thd->query, thd->query_length,
|
||||
transactional_tables, FALSE);
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
/*
|
||||
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,
|
||||
transactional_tables, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
>>>>>>>
|
||||
}
|
||||
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||
}
|
||||
|
@ -1946,12 +2039,25 @@ err2:
|
|||
bool multi_update::send_eof()
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
ulonglong id;
|
||||
DBUG_ENTER("multi_update::send_eof");
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
THD::killed_state killed_status= THD::NOT_KILLED;
|
||||
>>>>>>>
|
||||
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;
|
||||
/*
|
||||
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";
|
||||
|
||||
/* We must invalidate the query cache before binlog writing and
|
||||
|
@ -1978,6 +2084,12 @@ bool multi_update::send_eof()
|
|||
{
|
||||
if (local_error == 0)
|
||||
thd->clear_error();
|
||||
<<<<<<< gca sql/sql_update.cc 1.154.2.70
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_tables, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
||||
local_error= 1; // Rollback update
|
||||
<<<<<<< local sql/sql_update.cc 1.258
|
||||
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||
thd->query, thd->query_length,
|
||||
transactional_tables, FALSE) &&
|
||||
|
@ -1985,6 +2097,12 @@ bool multi_update::send_eof()
|
|||
{
|
||||
local_error= 1; // Rollback update
|
||||
}
|
||||
<<<<<<< remote sql/sql_update.cc 1.154.2.71
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_tables, FALSE, killed_status);
|
||||
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
||||
local_error= 1; // Rollback update
|
||||
>>>>>>>
|
||||
}
|
||||
if (thd->transaction.stmt.modified_non_trans_table)
|
||||
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||
|
|
Loading…
Add table
Reference in a new issue