mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01: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.
This commit is contained in:
parent
261a1e2033
commit
8e1d1e45f1
4 changed files with 198 additions and 0 deletions
|
@ -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) {
|
||||
/*
|
||||
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
|
||||
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
|
||||
eng "debug sync point hit limit reached"
|
||||
ger "Debug Sync Point Hit Limit erreicht"
|
||||
ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
|
||||
eng "Cannot modify @@session.binlog_format inside a transaction"
|
||||
|
|
Loading…
Reference in a new issue