mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
BUG#50479 DDL stmt on row-only/stmt-only tables generate spurious binlog_format
errors In the fix of BUG#39934 in 5.1-rep+3, errors are generated when binlog_format=row and a statement modifies a table restricted to statement-logging (ER_BINLOG_ROW_MODE_AND_STMT_ENGINE); or if binlog_format=statement and a statement modifies a table restricted to row-logging (ER_BINLOG_STMT_MODE_AND_ROW_ENGINE). However, some DDL statements that lock tables (e.g. ALTER TABLE, CREATE INDEX and CREATE TRIGGER) were causing spurious errors, although no row might be inserted into the binary log. To fix the problem, we tagged statements that may generate rows into the binary log and thence the warning messages are only printed out when the appropriate conditions hold and rows might be changed. sql/log_event.cc: Reorganized the Query_log_event's constructor based on the CF_CAN_GENERATE_ROW_EVENTS flag and as such any statement that has the associated flag should go through a cache before being written to the binary log. sql/share/errmsg-utf8.txt: Improved the error message ER_BINLOG_UNSAFE_MIXED_STATEMENT according to Paul's suggestion. sql/sql_class.cc: Created a hook to be used by innodb that checks if a statement may write rows to the binary log. In other words, if it has the CF_CAN_GENERATE_ROW_EVENTS flag associated. sql/sql_class.h: Defined the CF_CAN_GENERATE_ROW_EVENTS flag. sql/sql_parse.cc: Updated the sql_command_flags and added a function to check the CF_CAN_GENERATE_ROW_EVENTS. sql/sql_parse.h: Added a function to check the CF_CAN_GENERATE_ROW_EVENTS. storage/innobase/handler/ha_innodb.cc: Added a call to the hook thd_generates_rows(). storage/innobase/handler/ha_innodb.h: Defined an external reference to the hook thd_generates_rows().
This commit is contained in:
@ -8,14 +8,14 @@ INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2);
|
||||
INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2);
|
||||
UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
The last event before the COMMIT is use `test`; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c
|
||||
*** Please look in binlog_multi_engine.test if you have a diff here ****
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2);
|
||||
UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
|
||||
COMMIT;
|
||||
TRUNCATE t1m;
|
||||
|
53
mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result
Normal file
53
mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result
Normal file
@ -0,0 +1,53 @@
|
||||
SET @old_binlog_format= @@global.binlog_format;
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
################################################################################
|
||||
# Verifies if ER_BINLOG_STMT_MODE_AND_ROW_ENGINE happens by setting the binlog
|
||||
# format to STATEMENT and the transaction isolation level to READ COMMITTED as
|
||||
# such changes force Innodb to accept changes in the row format.
|
||||
#
|
||||
# When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed
|
||||
# any error should be triggered.
|
||||
#
|
||||
# In contrast, CREATE TABLE ... SELECT should trigger the following error:
|
||||
# ER_BINLOG_STMT_MODE_AND_ROW_ENGINE.
|
||||
################################################################################
|
||||
SET binlog_format = STATEMENT;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = InnoDB;
|
||||
ALTER TABLE t_row ADD COLUMN b INT;
|
||||
CREATE TRIGGER trig_row BEFORE INSERT ON t_row FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
||||
CREATE INDEX i ON t_row(a);
|
||||
CREATE TABLE t_row_new ENGINE = InnoDB SELECT * FROM t_row;
|
||||
ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
|
||||
DROP TABLE t_row;
|
||||
|
||||
|
||||
################################################################################
|
||||
# Verifies if ER_BINLOG_ROW_MODE_AND_STMT_ENGINE happens by setting the binlog
|
||||
# format to ROW and using a engine, i.e. EXAMPLE, that only supports STATEMENT.
|
||||
#
|
||||
# When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed
|
||||
# the error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE is not triggered. Note that other
|
||||
# errors are triggered due to restrictions in the engine.
|
||||
#
|
||||
# In contrast, CREATE TABLE ... SELECT should trigger the following error:
|
||||
# ER_BINLOG_ROW_MODE_AND_STMT_ENGINE.
|
||||
################################################################################
|
||||
SET binlog_format = ROW;
|
||||
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
||||
ALTER TABLE t_stmt ADD COLUMN b INT;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE'
|
||||
CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
||||
CREATE INDEX i ON t_stmt(a);
|
||||
ERROR 42000: Too many key parts specified; max 0 parts allowed
|
||||
CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt;
|
||||
ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-based logging.
|
||||
DROP TABLE t_stmt;
|
||||
|
||||
|
||||
################################################################################
|
||||
# CLEAN UP #
|
||||
################################################################################
|
||||
UNINSTALL PLUGIN example;
|
||||
SET @@global.binlog_format = @old_binlog_format;
|
||||
SET @@session.binlog_format = @old_binlog_format;
|
@ -8,7 +8,7 @@ begin;
|
||||
insert into t1 values(1);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
commit;
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
@ -23,7 +23,7 @@ begin;
|
||||
insert into t1 values(2);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
rollback;
|
||||
Warnings:
|
||||
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
@ -42,7 +42,7 @@ savepoint my_savepoint;
|
||||
insert into t1 values(4);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
rollback to savepoint my_savepoint;
|
||||
Warnings:
|
||||
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
@ -65,7 +65,7 @@ savepoint my_savepoint;
|
||||
insert into t1 values(6);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
rollback to savepoint my_savepoint;
|
||||
Warnings:
|
||||
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
@ -95,7 +95,7 @@ begin;
|
||||
insert into t1 values(8);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
select get_lock("a",10);
|
||||
get_lock("a",10)
|
||||
1
|
||||
@ -111,7 +111,7 @@ reset master;
|
||||
insert into t1 values(9);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
@ -127,7 +127,7 @@ insert into t1 values(10);
|
||||
begin;
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
@ -246,7 +246,7 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
create table t0 (n int);
|
||||
insert t0 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
set autocommit=1;
|
||||
insert into t0 select GET_LOCK("lock1",null);
|
||||
Warnings:
|
||||
@ -432,7 +432,7 @@ begin;
|
||||
insert into t1 values(8);
|
||||
insert into t2 select * from t1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements that read from both transactional (or a temporary table of any engine type) and non-transactional tables and write to any of them are unsafe.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.
|
||||
select get_lock("a",10);
|
||||
get_lock("a",10)
|
||||
1
|
||||
|
@ -0,0 +1 @@
|
||||
--innodb $EXAMPLE_PLUGIN_OPT
|
95
mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test
Normal file
95
mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test
Normal file
@ -0,0 +1,95 @@
|
||||
################################################################################
|
||||
# BUG#50479 DDL stmt on row-only/stmt-only tables generate spurious
|
||||
# binlog_format errors
|
||||
#
|
||||
# In the fix of BUG#39934 in 5.1-rep+3, errors are generated when
|
||||
# binlog_format=row and a statement modifies a table restricted to
|
||||
# statement-logging (ER_BINLOG_ROW_MODE_AND_STMT_ENGINE); or if
|
||||
# binlog_format=statement and a statement modifies a table limited to
|
||||
# row-logging (ER_BINLOG_STMT_MODE_AND_ROW_ENGINE).
|
||||
#
|
||||
# In this test case, we check if some DDL statements that lock tables do not
|
||||
# trigger errors as they do not generate rows events and as such are harmless
|
||||
# from the point of view of conflicts between the engine's supported logging
|
||||
# format and the value of binlog_format.
|
||||
#
|
||||
# In particular, we check if:
|
||||
# 1 - ALTER TABLE, CREATE INDEX and CREATE TRIGGER do not generate either
|
||||
# ER_BINLOG_STMT_MODE_AND_ROW_ENGINE or ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
|
||||
#
|
||||
# 2 - CREATE TABLE ... SELECT generates an error because the command can
|
||||
# generate row events but CREATE TABLE without SELECT does not generate
|
||||
# an error.
|
||||
################################################################################
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_example_plugin.inc
|
||||
--source include/have_log_bin.inc
|
||||
|
||||
SET @old_binlog_format= @@global.binlog_format;
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
|
||||
--echo ################################################################################
|
||||
--echo # Verifies if ER_BINLOG_STMT_MODE_AND_ROW_ENGINE happens by setting the binlog
|
||||
--echo # format to STATEMENT and the transaction isolation level to READ COMMITTED as
|
||||
--echo # such changes force Innodb to accept changes in the row format.
|
||||
--echo #
|
||||
--echo # When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed
|
||||
--echo # any error should be triggered.
|
||||
--echo #
|
||||
--echo # In contrast, CREATE TABLE ... SELECT should trigger the following error:
|
||||
--echo # ER_BINLOG_STMT_MODE_AND_ROW_ENGINE.
|
||||
--echo ################################################################################
|
||||
SET binlog_format = STATEMENT;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = InnoDB;
|
||||
|
||||
ALTER TABLE t_row ADD COLUMN b INT;
|
||||
|
||||
CREATE TRIGGER trig_row BEFORE INSERT ON t_row FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
||||
|
||||
CREATE INDEX i ON t_row(a);
|
||||
|
||||
--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
|
||||
CREATE TABLE t_row_new ENGINE = InnoDB SELECT * FROM t_row;
|
||||
|
||||
DROP TABLE t_row;
|
||||
|
||||
--echo
|
||||
--echo
|
||||
|
||||
--echo ################################################################################
|
||||
--echo # Verifies if ER_BINLOG_ROW_MODE_AND_STMT_ENGINE happens by setting the binlog
|
||||
--echo # format to ROW and using a engine, i.e. EXAMPLE, that only supports STATEMENT.
|
||||
--echo #
|
||||
--echo # When CREATE TABLE, ALTER TABLE, CREATE INDEX and CREATE TRIGGER are executed
|
||||
--echo # the error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE is not triggered. Note that other
|
||||
--echo # errors are triggered due to restrictions in the engine.
|
||||
--echo #
|
||||
--echo # In contrast, CREATE TABLE ... SELECT should trigger the following error:
|
||||
--echo # ER_BINLOG_ROW_MODE_AND_STMT_ENGINE.
|
||||
--echo ################################################################################
|
||||
SET binlog_format = ROW;
|
||||
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
||||
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
ALTER TABLE t_stmt ADD COLUMN b INT;
|
||||
|
||||
CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
||||
|
||||
--error ER_TOO_MANY_KEY_PARTS
|
||||
CREATE INDEX i ON t_stmt(a);
|
||||
|
||||
--error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
|
||||
CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt;
|
||||
|
||||
DROP TABLE t_stmt;
|
||||
|
||||
--echo
|
||||
--echo
|
||||
|
||||
--echo ################################################################################
|
||||
--echo # CLEAN UP #
|
||||
--echo ################################################################################
|
||||
UNINSTALL PLUGIN example;
|
||||
SET @@global.binlog_format = @old_binlog_format;
|
||||
SET @@session.binlog_format = @old_binlog_format;
|
Reference in New Issue
Block a user