Skip to content

Commit 0c4b0e9

Browse files
authored andcommitted
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.
1 parent ce9f2d4 commit 0c4b0e9

File tree

3 files changed

+173
-17
lines changed

3 files changed

+173
-17
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
SELECT @@SESSION.binlog_format;
2+
@@SESSION.binlog_format
3+
MIXED
4+
CREATE TABLE t1 (a VARCHAR(100));
5+
CREATE TEMPORARY TABLE t2 (a VARCHAR(100));
6+
# Test allow switching @@SESSION.binlog_format from MIXED to STATEMENT
7+
# when there are open temp tables and we are logging in statement based format.
8+
SET SESSION binlog_format = STATEMENT;
9+
SELECT @@SESSION.binlog_format;
10+
@@SESSION.binlog_format
11+
STATEMENT
12+
# Test allow switching @@SESSION.binlog_format from STATEMENT to
13+
# STATEMENT when there are open temp tables.
14+
SET SESSION binlog_format = STATEMENT;
15+
SELECT @@SESSION.binlog_format;
16+
@@SESSION.binlog_format
17+
STATEMENT
18+
INSERT INTO t1 VALUES ('statement based');
19+
SELECT @@SESSION.binlog_format;
20+
@@SESSION.binlog_format
21+
STATEMENT
22+
# Test allow switching @@SESSION.binlog_format from STATEMENT to
23+
# MIXED when there are open temp tables.
24+
SET SESSION binlog_format = MIXED;
25+
SELECT @@SESSION.binlog_format;
26+
@@SESSION.binlog_format
27+
MIXED
28+
# Test allow switching @@SESSION.binlog_format from MIXED to MIXED
29+
# when there are open temp tables.
30+
SET SESSION binlog_format = MIXED;
31+
SELECT @@SESSION.binlog_format;
32+
@@SESSION.binlog_format
33+
MIXED
34+
INSERT INTO t2 VALUES (UUID());
35+
SELECT @@SESSION.binlog_format;
36+
@@SESSION.binlog_format
37+
MIXED
38+
# Test forbit switching @@SESSION.binlog_format from MIXED to STATEMENT
39+
# when there are open temp tables and we are logging in row based format.
40+
SET SESSION binlog_format = STATEMENT;
41+
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
42+
SELECT @@SESSION.binlog_format;
43+
@@SESSION.binlog_format
44+
MIXED
45+
SET SESSION binlog_format = ROW;
46+
SELECT @@SESSION.binlog_format;
47+
@@SESSION.binlog_format
48+
ROW
49+
INSERT INTO t1 VALUES ('row based');
50+
# Test allow switching @@SESSION.binlog_format from ROW to MIXED
51+
# when there are open temp tables.
52+
SET SESSION binlog_format = MIXED;
53+
SELECT @@SESSION.binlog_format;
54+
@@SESSION.binlog_format
55+
MIXED
56+
INSERT INTO t1 VALUES ('row based');
57+
# Test allow switching @@SESSION.binlog_format from MIXED to ROW
58+
# when there are open temp tables.
59+
SET SESSION binlog_format = ROW;
60+
SELECT @@SESSION.binlog_format;
61+
@@SESSION.binlog_format
62+
ROW
63+
# Test allow switching @@SESSION.binlog_format from ROW to ROW
64+
# when there are open temp tables.
65+
SET SESSION binlog_format = ROW;
66+
SELECT @@SESSION.binlog_format;
67+
@@SESSION.binlog_format
68+
ROW
69+
INSERT INTO t1 VALUES ('row based');
70+
# Test forbit switching @@SESSION.binlog_format from ROW to STATEMENT
71+
# when there are open temp tables.
72+
SET SESSION binlog_format = STATEMENT;
73+
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
74+
SELECT @@SESSION.binlog_format;
75+
@@SESSION.binlog_format
76+
ROW
77+
DROP TEMPORARY TABLE t2;
78+
DROP TABLE t1;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#
2+
# Bug #45855 row events in binlog after switch from binlog_fmt=mix to stmt with open tmp tbl
3+
# Bug #45856 can't switch from binlog_format=row to mix with open tmp tbl
4+
# This test verfies if the program will generate ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
5+
# error and forbid switching @@SESSION.binlog_format from MIXED or ROW to
6+
# STATEMENT when there are open temp tables and we are logging in row format.
7+
# There is no error in any other case.
8+
#
9+
10+
source include/have_binlog_format_mixed.inc;
11+
12+
SELECT @@SESSION.binlog_format;
13+
CREATE TABLE t1 (a VARCHAR(100));
14+
CREATE TEMPORARY TABLE t2 (a VARCHAR(100));
15+
16+
--echo # Test allow switching @@SESSION.binlog_format from MIXED to STATEMENT
17+
--echo # when there are open temp tables and we are logging in statement based format.
18+
SET SESSION binlog_format = STATEMENT;
19+
SELECT @@SESSION.binlog_format;
20+
21+
--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to
22+
--echo # STATEMENT when there are open temp tables.
23+
SET SESSION binlog_format = STATEMENT;
24+
SELECT @@SESSION.binlog_format;
25+
26+
INSERT INTO t1 VALUES ('statement based');
27+
SELECT @@SESSION.binlog_format;
28+
--echo # Test allow switching @@SESSION.binlog_format from STATEMENT to
29+
--echo # MIXED when there are open temp tables.
30+
SET SESSION binlog_format = MIXED;
31+
SELECT @@SESSION.binlog_format;
32+
33+
--echo # Test allow switching @@SESSION.binlog_format from MIXED to MIXED
34+
--echo # when there are open temp tables.
35+
SET SESSION binlog_format = MIXED;
36+
SELECT @@SESSION.binlog_format;
37+
38+
INSERT INTO t2 VALUES (UUID());
39+
SELECT @@SESSION.binlog_format;
40+
41+
--echo # Test forbit switching @@SESSION.binlog_format from MIXED to STATEMENT
42+
--echo # when there are open temp tables and we are logging in row based format.
43+
--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
44+
SET SESSION binlog_format = STATEMENT;
45+
SELECT @@SESSION.binlog_format;
46+
47+
SET SESSION binlog_format = ROW;
48+
SELECT @@SESSION.binlog_format;
49+
50+
INSERT INTO t1 VALUES ('row based');
51+
--echo # Test allow switching @@SESSION.binlog_format from ROW to MIXED
52+
--echo # when there are open temp tables.
53+
SET SESSION binlog_format = MIXED;
54+
SELECT @@SESSION.binlog_format;
55+
56+
INSERT INTO t1 VALUES ('row based');
57+
--echo # Test allow switching @@SESSION.binlog_format from MIXED to ROW
58+
--echo # when there are open temp tables.
59+
SET SESSION binlog_format = ROW;
60+
SELECT @@SESSION.binlog_format;
61+
62+
--echo # Test allow switching @@SESSION.binlog_format from ROW to ROW
63+
--echo # when there are open temp tables.
64+
SET SESSION binlog_format = ROW;
65+
SELECT @@SESSION.binlog_format;
66+
67+
INSERT INTO t1 VALUES ('row based');
68+
--echo # Test forbit switching @@SESSION.binlog_format from ROW to STATEMENT
69+
--echo # when there are open temp tables.
70+
--ERROR ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
71+
SET SESSION binlog_format = STATEMENT;
72+
SELECT @@SESSION.binlog_format;
73+
74+
DROP TEMPORARY TABLE t2;
75+
DROP TABLE t1;
76+

sql/set_var.cc

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,32 +1294,34 @@ bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
12941294
bool result= sys_var_thd_enum::check(thd, var);
12951295
if (!result)
12961296
result= check_log_update(thd, var);
1297-
return result;
1298-
}
1299-
1300-
bool sys_var_thd_binlog_format::is_readonly() const
1301-
{
1302-
/*
1303-
Under certain circumstances, the variable is read-only (unchangeable):
1304-
*/
1305-
THD *thd= current_thd;
13061297
/*
13071298
If RBR and open temporary tables, their CREATE TABLE may not be in the
13081299
binlog, so we can't toggle to SBR in this connection.
1309-
The test below will also prevent SET GLOBAL, well it was not easy to test
1310-
if global or not here.
1311-
And this test will also prevent switching from RBR to RBR (a no-op which
1312-
should not happen too often).
13131300
1314-
If we don't have row-based replication compiled in, the variable
1315-
is always read-only.
1301+
If binlog_format=MIXED, there are open temporary tables, and an unsafe
1302+
statement is executed, then subsequent statements are logged in row
1303+
format and hence changes to temporary tables may be lost. So we forbid
1304+
switching @@SESSION.binlog_format from MIXED to STATEMENT when there are
1305+
open temp tables and we are logging in row format.
13161306
*/
1317-
if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) &&
1318-
thd->temporary_tables)
1307+
if (thd->temporary_tables && var->type == OPT_SESSION &&
1308+
var->save_result.ulong_value == BINLOG_FORMAT_STMT &&
1309+
((thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
1310+
thd->is_current_stmt_binlog_format_row()) ||
1311+
thd->variables.binlog_format == BINLOG_FORMAT_ROW))
13191312
{
13201313
my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0));
13211314
return 1;
13221315
}
1316+
return result;
1317+
}
1318+
1319+
bool sys_var_thd_binlog_format::is_readonly() const
1320+
{
1321+
/*
1322+
Under certain circumstances, the variable is read-only (unchangeable):
1323+
*/
1324+
THD *thd= current_thd;
13231325
/*
13241326
if in a stored function/trigger, it's too late to change mode
13251327
*/

0 commit comments

Comments
 (0)