mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Bug #45855 row events in binlog after switch from binlog_fmt=mix to stmt with open tmp tbl
Bug #45856 can't switch from binlog_format=row to mix with open tmp tbl If binlog_format=MIXED, there are open temporary tables, an unsafe statement is executed, and the user issues 'SET @@session.binlog_format = STATEMENT', then subsequent DML statements will be written in row format despite binlog_format=STATEMENT. Because the binlog format can't be reset to statement based by 'reset_current_stmt_binlog_row_based' function. If binlog_format=ROW, there are open temporary tables, and an unsafe statement is executed, then the statement 'SET @@session.binlog_format = MIXED' generates the error: "Cannot switch out of the row-based binary log format when the session has open temporary tables" However, it is safe to switch to MIXED mode because events in row format are allowed. To fix the above two problems, generate ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR and forbid switching from MIXED or ROW to STATEMENT when there are open temp tables and we are logging in row format. There is no error in any other case.
This commit is contained in:
parent
ce9f2d4cad
commit
0c4b0e9a3a
3 changed files with 173 additions and 17 deletions
|
@ -0,0 +1,78 @@
|
|||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
MIXED
|
||||
CREATE TABLE t1 (a VARCHAR(100));
|
||||
CREATE TEMPORARY TABLE t2 (a VARCHAR(100));
|
||||
# Test allow switching @@SESSION.binlog_format from MIXED to STATEMENT
|
||||
# when there are open temp tables and we are logging in statement based format.
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
STATEMENT
|
||||
# Test allow switching @@SESSION.binlog_format from STATEMENT to
|
||||
# STATEMENT when there are open temp tables.
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
STATEMENT
|
||||
INSERT INTO t1 VALUES ('statement based');
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
STATEMENT
|
||||
# Test allow switching @@SESSION.binlog_format from STATEMENT to
|
||||
# MIXED when there are open temp tables.
|
||||
SET SESSION binlog_format = MIXED;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
MIXED
|
||||
# Test allow switching @@SESSION.binlog_format from MIXED to MIXED
|
||||
# when there are open temp tables.
|
||||
SET SESSION binlog_format = MIXED;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
MIXED
|
||||
INSERT INTO t2 VALUES (UUID());
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
MIXED
|
||||
# Test forbit switching @@SESSION.binlog_format from MIXED to STATEMENT
|
||||
# when there are open temp tables and we are logging in row based format.
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
MIXED
|
||||
SET SESSION binlog_format = ROW;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
ROW
|
||||
INSERT INTO t1 VALUES ('row based');
|
||||
# Test allow switching @@SESSION.binlog_format from ROW to MIXED
|
||||
# when there are open temp tables.
|
||||
SET SESSION binlog_format = MIXED;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
MIXED
|
||||
INSERT INTO t1 VALUES ('row based');
|
||||
# Test allow switching @@SESSION.binlog_format from MIXED to ROW
|
||||
# when there are open temp tables.
|
||||
SET SESSION binlog_format = ROW;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
ROW
|
||||
# Test allow switching @@SESSION.binlog_format from ROW to ROW
|
||||
# when there are open temp tables.
|
||||
SET SESSION binlog_format = ROW;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
ROW
|
||||
INSERT INTO t1 VALUES ('row based');
|
||||
# Test forbit switching @@SESSION.binlog_format from ROW to STATEMENT
|
||||
# when there are open temp tables.
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
|
||||
SELECT @@SESSION.binlog_format;
|
||||
@@SESSION.binlog_format
|
||||
ROW
|
||||
DROP TEMPORARY TABLE t2;
|
||||
DROP TABLE t1;
|
|
@ -0,0 +1,76 @@
|
|||
#
|
||||
# Bug #45855 row events in binlog after switch from binlog_fmt=mix to stmt with open tmp tbl
|
||||
# Bug #45856 can't switch from binlog_format=row to mix with open tmp tbl
|
||||
# This test verfies if the program will generate ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
|
||||
# error and forbid switching @@SESSION.binlog_format from MIXED or ROW to
|
||||
# STATEMENT when there are open temp tables and we are logging in row format.
|
||||
# There is no error in any other case.
|
||||
#
|
||||
|
||||
source include/have_binlog_format_mixed.inc;
|
||||
|
||||
SELECT @@SESSION.binlog_format;
|
||||
CREATE TABLE t1 (a VARCHAR(100));
|
||||
CREATE TEMPORARY TABLE t2 (a VARCHAR(100));
|
||||
|
||||
--echo # Test allow switching @@SESSION.binlog_format from MIXED to STATEMENT
|
||||
--echo # when there are open temp tables and we are logging in statement based format.
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to
|
||||
--echo # STATEMENT when there are open temp tables.
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
INSERT INTO t1 VALUES ('statement based');
|
||||
SELECT @@SESSION.binlog_format;
|
||||
--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to
|
||||
--echo # MIXED when there are open temp tables.
|
||||
SET SESSION binlog_format = MIXED;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
--echo # Test allow switching @@SESSION.binlog_format from MIXED to MIXED
|
||||
--echo # when there are open temp tables.
|
||||
SET SESSION binlog_format = MIXED;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
INSERT INTO t2 VALUES (UUID());
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
--echo # Test forbit switching @@SESSION.binlog_format from MIXED to STATEMENT
|
||||
--echo # when there are open temp tables and we are logging in row based format.
|
||||
--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
SET SESSION binlog_format = ROW;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
INSERT INTO t1 VALUES ('row based');
|
||||
--echo # Test allow switching @@SESSION.binlog_format from ROW to MIXED
|
||||
--echo # when there are open temp tables.
|
||||
SET SESSION binlog_format = MIXED;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
INSERT INTO t1 VALUES ('row based');
|
||||
--echo # Test allow switching @@SESSION.binlog_format from MIXED to ROW
|
||||
--echo # when there are open temp tables.
|
||||
SET SESSION binlog_format = ROW;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
--echo # Test allow switching @@SESSION.binlog_format from ROW to ROW
|
||||
--echo # when there are open temp tables.
|
||||
SET SESSION binlog_format = ROW;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
INSERT INTO t1 VALUES ('row based');
|
||||
--echo # Test forbit switching @@SESSION.binlog_format from ROW to STATEMENT
|
||||
--echo # when there are open temp tables.
|
||||
--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
|
||||
SET SESSION binlog_format = STATEMENT;
|
||||
SELECT @@SESSION.binlog_format;
|
||||
|
||||
DROP TEMPORARY TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
|
@ -1294,6 +1294,25 @@ bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
|
|||
bool result= sys_var_thd_enum::check(thd, var);
|
||||
if (!result)
|
||||
result= check_log_update(thd, var);
|
||||
/*
|
||||
If RBR and open temporary tables, their CREATE TABLE may not be in the
|
||||
binlog, so we can't toggle to SBR in this connection.
|
||||
|
||||
If binlog_format=MIXED, there are open temporary tables, and an unsafe
|
||||
statement is executed, then subsequent statements are logged in row
|
||||
format and hence changes to temporary tables may be lost. So we forbid
|
||||
switching @@SESSION.binlog_format from MIXED to STATEMENT when there are
|
||||
open temp tables and we are logging in row format.
|
||||
*/
|
||||
if (thd->temporary_tables && var->type == OPT_SESSION &&
|
||||
var->save_result.ulong_value == BINLOG_FORMAT_STMT &&
|
||||
((thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
|
||||
thd->is_current_stmt_binlog_format_row()) ||
|
||||
thd->variables.binlog_format == BINLOG_FORMAT_ROW))
|
||||
{
|
||||
my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1303,23 +1322,6 @@ bool sys_var_thd_binlog_format::is_readonly() const
|
|||
Under certain circumstances, the variable is read-only (unchangeable):
|
||||
*/
|
||||
THD *thd= current_thd;
|
||||
/*
|
||||
If RBR and open temporary tables, their CREATE TABLE may not be in the
|
||||
binlog, so we can't toggle to SBR in this connection.
|
||||
The test below will also prevent SET GLOBAL, well it was not easy to test
|
||||
if global or not here.
|
||||
And this test will also prevent switching from RBR to RBR (a no-op which
|
||||
should not happen too often).
|
||||
|
||||
If we don't have row-based replication compiled in, the variable
|
||||
is always read-only.
|
||||
*/
|
||||
if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) &&
|
||||
thd->temporary_tables)
|
||||
{
|
||||
my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
if in a stored function/trigger, it's too late to change mode
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue