mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
@ -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;
|
||||||
|
|
@ -1244,6 +1244,14 @@ void fix_slave_exec_mode(enum_var_type type)
|
|||||||
|
|
||||||
|
|
||||||
bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
|
bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
|
||||||
|
/*
|
||||||
|
Make the session variable 'binlog_format' read-only inside a transaction.
|
||||||
|
*/
|
||||||
|
if (thd->active_transaction() && (var->type == OPT_SESSION))
|
||||||
|
{
|
||||||
|
my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
All variables that affect writing to binary log (either format or
|
All variables that affect writing to binary log (either format or
|
||||||
turning logging on and off) use the same checking. We call the
|
turning logging on and off) use the same checking. We call the
|
||||||
|
@ -6249,3 +6249,5 @@ ER_DEBUG_SYNC_TIMEOUT
|
|||||||
ER_DEBUG_SYNC_HIT_LIMIT
|
ER_DEBUG_SYNC_HIT_LIMIT
|
||||||
eng "debug sync point hit limit reached"
|
eng "debug sync point hit limit reached"
|
||||||
ger "Debug Sync Point Hit Limit erreicht"
|
ger "Debug Sync Point Hit Limit erreicht"
|
||||||
|
ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
|
||||||
|
eng "Cannot modify @@session.binlog_format inside a transaction"
|
||||||
|
Reference in New Issue
Block a user