Browse Source
Bug #47863 binlog_format should be writable only at transaction boundaries
Bug #47863 binlog_format should be writable only at transaction boundaries
When @@session.binlog_format is modified inside a transaction,
it can cause slave to go out of sync.
To fix the problem, make the session variable 'binlog_format'
read-only inside a transaction.
mysql-test/suite/binlog/r/binlog_format_switch_inside_trans.result:
Test result for bug#47863.
mysql-test/suite/binlog/t/binlog_format_switch_inside_trans.test:
Added test file to verify if the session variable 'binlog_format'
is read-only inside a transaction and in sub-statements.
sql/set_var.cc:
Added code to make the session variable 'binlog_format'
read-only inside a transaction.
pull/374/head
4 changed files with 198 additions and 0 deletions
-
90mysql-test/suite/binlog/r/binlog_format_switch_inside_trans.result
-
98mysql-test/suite/binlog/t/binlog_format_switch_inside_trans.test
-
8sql/set_var.cc
-
2sql/share/errmsg.txt
@ -0,0 +1,90 @@ |
|||||
|
set @save_binlog_format= @@global.binlog_format; |
||||
|
create table t1 (a int) engine= myisam; |
||||
|
create table t2 (a int) engine= innodb; |
||||
|
SELECT @@session.binlog_format; |
||||
|
@@session.binlog_format |
||||
|
ROW |
||||
|
SET AUTOCOMMIT=1; |
||||
|
# Test that the session variable 'binlog_format' |
||||
|
# is writable outside a transaction. |
||||
|
set @@session.binlog_format= statement; |
||||
|
SELECT @@session.binlog_format; |
||||
|
@@session.binlog_format |
||||
|
STATEMENT |
||||
|
begin; |
||||
|
# Test that the session variable 'binlog_format' is read-only |
||||
|
# inside a transaction with no preceding updates. |
||||
|
set @@session.binlog_format= mixed; |
||||
|
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction |
||||
|
insert into t2 values (1); |
||||
|
# Test that the session variable 'binlog_format' is read-only |
||||
|
# inside a transaction with preceding transactional updates. |
||||
|
set @@session.binlog_format= row; |
||||
|
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction |
||||
|
commit; |
||||
|
begin; |
||||
|
insert into t1 values (2); |
||||
|
# Test that the session variable 'binlog_format' is read-only |
||||
|
# inside a transaction with preceding non-transactional updates. |
||||
|
set @@session.binlog_format= statement; |
||||
|
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction |
||||
|
commit; |
||||
|
# Test that the session variable 'binlog_format' is writable |
||||
|
# when AUTOCOMMIT=0, before a transaction has started. |
||||
|
set AUTOCOMMIT=0; |
||||
|
set @@session.binlog_format= row; |
||||
|
SELECT @@session.binlog_format; |
||||
|
@@session.binlog_format |
||||
|
ROW |
||||
|
insert into t1 values (4); |
||||
|
# Test that the session variable 'binlog_format' is read-only inside an |
||||
|
# AUTOCOMMIT=0 transaction with preceding non-transactional updates. |
||||
|
set @@session.binlog_format= statement; |
||||
|
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction |
||||
|
SELECT @@session.binlog_format; |
||||
|
@@session.binlog_format |
||||
|
ROW |
||||
|
commit; |
||||
|
insert into t2 values (5); |
||||
|
# Test that the session variable 'binlog_format' is read-only inside an |
||||
|
# AUTOCOMMIT=0 transaction with preceding transactional updates. |
||||
|
set @@session.binlog_format= row; |
||||
|
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction |
||||
|
SELECT @@session.binlog_format; |
||||
|
@@session.binlog_format |
||||
|
ROW |
||||
|
commit; |
||||
|
begin; |
||||
|
insert into t2 values (6); |
||||
|
# Test that the global variable 'binlog_format' is writable |
||||
|
# inside a transaction. |
||||
|
SELECT @@global.binlog_format; |
||||
|
@@global.binlog_format |
||||
|
ROW |
||||
|
set @@global.binlog_format= statement; |
||||
|
SELECT @@global.binlog_format; |
||||
|
@@global.binlog_format |
||||
|
STATEMENT |
||||
|
commit; |
||||
|
set @@global.binlog_format= @save_binlog_format; |
||||
|
create table t3(a int, b int) engine= innodb; |
||||
|
create table t4(a int) engine= innodb; |
||||
|
create table t5(a int) engine= innodb; |
||||
|
create trigger tr2 after insert on t3 for each row begin |
||||
|
insert into t4(a) values(1); |
||||
|
set @@session.binlog_format= statement; |
||||
|
insert into t4(a) values(2); |
||||
|
insert into t5(a) values(3); |
||||
|
end | |
||||
|
# Test that the session variable 'binlog_format' is read-only |
||||
|
# in sub-statements. |
||||
|
insert into t3(a,b) values(1,1); |
||||
|
ERROR HY000: Cannot change the binary logging format inside a stored function or trigger |
||||
|
SELECT @@session.binlog_format; |
||||
|
@@session.binlog_format |
||||
|
ROW |
||||
|
drop table t1; |
||||
|
drop table t2; |
||||
|
drop table t3; |
||||
|
drop table t4; |
||||
|
drop table t5; |
||||
@ -0,0 +1,98 @@ |
|||||
|
# |
||||
|
# BUG#47863 |
||||
|
# This test verifies if the session variable 'binlog_format' |
||||
|
# is read-only inside a transaction and in sub-statements. |
||||
|
# |
||||
|
|
||||
|
source include/have_innodb.inc; |
||||
|
source include/have_binlog_format_row.inc; |
||||
|
|
||||
|
set @save_binlog_format= @@global.binlog_format; |
||||
|
create table t1 (a int) engine= myisam; |
||||
|
create table t2 (a int) engine= innodb; |
||||
|
|
||||
|
SELECT @@session.binlog_format; |
||||
|
SET AUTOCOMMIT=1; |
||||
|
--echo # Test that the session variable 'binlog_format' |
||||
|
--echo # is writable outside a transaction. |
||||
|
set @@session.binlog_format= statement; |
||||
|
SELECT @@session.binlog_format; |
||||
|
|
||||
|
begin; |
||||
|
--echo # Test that the session variable 'binlog_format' is read-only |
||||
|
--echo # inside a transaction with no preceding updates. |
||||
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT |
||||
|
set @@session.binlog_format= mixed; |
||||
|
|
||||
|
insert into t2 values (1); |
||||
|
--echo # Test that the session variable 'binlog_format' is read-only |
||||
|
--echo # inside a transaction with preceding transactional updates. |
||||
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT |
||||
|
set @@session.binlog_format= row; |
||||
|
commit; |
||||
|
|
||||
|
begin; |
||||
|
insert into t1 values (2); |
||||
|
--echo # Test that the session variable 'binlog_format' is read-only |
||||
|
--echo # inside a transaction with preceding non-transactional updates. |
||||
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT |
||||
|
set @@session.binlog_format= statement; |
||||
|
commit; |
||||
|
|
||||
|
--echo # Test that the session variable 'binlog_format' is writable |
||||
|
--echo # when AUTOCOMMIT=0, before a transaction has started. |
||||
|
set AUTOCOMMIT=0; |
||||
|
set @@session.binlog_format= row; |
||||
|
SELECT @@session.binlog_format; |
||||
|
|
||||
|
insert into t1 values (4); |
||||
|
--echo # Test that the session variable 'binlog_format' is read-only inside an |
||||
|
--echo # AUTOCOMMIT=0 transaction with preceding non-transactional updates. |
||||
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT |
||||
|
set @@session.binlog_format= statement; |
||||
|
SELECT @@session.binlog_format; |
||||
|
commit; |
||||
|
|
||||
|
insert into t2 values (5); |
||||
|
--echo # Test that the session variable 'binlog_format' is read-only inside an |
||||
|
--echo # AUTOCOMMIT=0 transaction with preceding transactional updates. |
||||
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT |
||||
|
set @@session.binlog_format= row; |
||||
|
SELECT @@session.binlog_format; |
||||
|
commit; |
||||
|
|
||||
|
begin; |
||||
|
insert into t2 values (6); |
||||
|
--echo # Test that the global variable 'binlog_format' is writable |
||||
|
--echo # inside a transaction. |
||||
|
SELECT @@global.binlog_format; |
||||
|
set @@global.binlog_format= statement; |
||||
|
SELECT @@global.binlog_format; |
||||
|
commit; |
||||
|
|
||||
|
set @@global.binlog_format= @save_binlog_format; |
||||
|
|
||||
|
create table t3(a int, b int) engine= innodb; |
||||
|
create table t4(a int) engine= innodb; |
||||
|
create table t5(a int) engine= innodb; |
||||
|
delimiter |; |
||||
|
eval create trigger tr2 after insert on t3 for each row begin |
||||
|
insert into t4(a) values(1); |
||||
|
set @@session.binlog_format= statement; |
||||
|
insert into t4(a) values(2); |
||||
|
insert into t5(a) values(3); |
||||
|
end | |
||||
|
delimiter ;| |
||||
|
|
||||
|
--echo # Test that the session variable 'binlog_format' is read-only |
||||
|
--echo # in sub-statements. |
||||
|
--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT |
||||
|
insert into t3(a,b) values(1,1); |
||||
|
SELECT @@session.binlog_format; |
||||
|
|
||||
|
drop table t1; |
||||
|
drop table t2; |
||||
|
drop table t3; |
||||
|
drop table t4; |
||||
|
drop table t5; |
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue