mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
BUG#39934: Slave stops for engine that only support row-based logging
Post-push fix. Problem: After the original bugfix, if a statement is unsafe, binlog_format=mixed, and engine is statement-only, a warning was generated and the statement executed. However, it is a fundamental principle of binlogging that binlog_format=mixed should guarantee correct logging, no compromise. So correct behavior is to generate an error and don't execute the statement. Fix: Generate error instead of warning. Since issue_unsafe_warnings can only generate one error message, this allows us to simplify the code a bit too: decide_logging_format does not have to save the error code for issue_unsafe_warnings mysql-test/suite/binlog/r/binlog_statement_insert_delayed.result: updated result file mysql-test/suite/binlog/r/binlog_stm_ps.result: updated result file mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result: updated result file mysql-test/suite/binlog/r/binlog_unsafe.result: updated result file mysql-test/suite/rpl/r/rpl_stm_found_rows.result: updated result file mysql-test/suite/rpl/r/rpl_stm_loadfile.result: updated result file mysql-test/suite/rpl_ndb/r/rpl_ndb_binlog_format_errors.result: updated result file mysql-test/suite/rpl_ndb/t/rpl_ndb_binlog_format_errors.test: updated test: - ER_BINLOG_UNSAFE_AND_STMT_ENGINE is now an error. - added test for multiple types of unsafety sql/share/errmsg.txt: - Reformulated ER_BINLOG_UNSAFE_AND_STMT_ENGINE to reflect that it is now an error, not a warning. - Added "Reason for unsafeness" to ER_BINLOG_UNSAFE_STATEMENT and ER_BINLOG_UNSAFE_AND_STMT_ENGINE. sql/sql_class.cc: In decide_logging_format: - generate an error immediately in case 3, instead of scheduling a warning to be generated later. also updated comments accordingly - in case 7, there is only one unsafe warning error code now, so we don't need to store it in binlog_unsafe_warning_flags (see changes in sql_lex.h) - fixed compilation warning in DBUG_PRINT In issue_binlog_warning: - moved array of error codes to sql_lex.h (so that they are accessible also from decide_logging_format) - simplified code after the first set of bits in binlog_unsafe_warning_flags was removed sql/sql_class.h: - got rid of enum_binlog_stmt_warning. It's not needed anymore since we only have one type of unsafe warning (one of them turned into an error) - updated comments accordingly sql/sql_lex.cc: added initialization of the array of error codes that has been moved from THD::issue_unsafe_warnings to LEX. sql/sql_lex.h: Moved array of error codes from THD::issue_unsafe_warnings to LEX.
This commit is contained in:
@ -13,10 +13,10 @@ master-bin.000001 # Query # # use `test`; insert delayed into t1 values (300)
|
|||||||
master-bin.000001 # Query # # use `test`; FLUSH TABLES
|
master-bin.000001 # Query # # use `test`; FLUSH TABLES
|
||||||
insert delayed into t1 values (null),(null),(null),(null);
|
insert delayed into t1 values (null),(null),(null),(null);
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
|
||||||
insert delayed into t1 values (null),(null),(400),(null);
|
insert delayed into t1 values (null),(null),(400),(null);
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
207
|
207
|
||||||
|
@ -11,7 +11,7 @@ prepare s from "insert into t1 select 100 limit ?";
|
|||||||
set @a=100;
|
set @a=100;
|
||||||
execute s using @a;
|
execute s using @a;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
||||||
show binlog events from <binlog_start>;
|
show binlog events from <binlog_start>;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000001 # Query # # use `test`; create table t1 (a int)
|
master-bin.000001 # Query # # use `test`; create table t1 (a int)
|
||||||
|
@ -4,10 +4,10 @@ CREATE TABLE t1 (a int, b int, primary key (a));
|
|||||||
INSERT INTO t1 VALUES (1,2), (2,3);
|
INSERT INTO t1 VALUES (1,2), (2,3);
|
||||||
UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
|
UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
||||||
UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
|
UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown
|
### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown
|
||||||
SET SQL_LOG_BIN= 0;
|
SET SQL_LOG_BIN= 0;
|
||||||
@ -38,11 +38,11 @@ CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(10));
|
|||||||
SET GLOBAL LOG_WARNINGS = 0;
|
SET GLOBAL LOG_WARNINGS = 0;
|
||||||
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
|
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
SET GLOBAL LOG_WARNINGS = 1;
|
SET GLOBAL LOG_WARNINGS = 1;
|
||||||
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
|
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET GLOBAL log_warnings = @old_log_warnings;
|
SET GLOBAL log_warnings = @old_log_warnings;
|
||||||
# Count the number of times the "Unsafe" message was printed
|
# Count the number of times the "Unsafe" message was printed
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -52,8 +52,8 @@ a
|
|||||||
a
|
a
|
||||||
7
|
7
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
|
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
|
||||||
INSERT INTO logtbl VALUES (sect,test,found_rows);
|
INSERT INTO logtbl VALUES (sect,test,found_rows);
|
||||||
END $$
|
END $$
|
||||||
|
@ -10,7 +10,7 @@ CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, PRIMARY KEY(a));
|
|||||||
INSERT INTO test.t1 VALUES(1,'test');
|
INSERT INTO test.t1 VALUES(1,'test');
|
||||||
UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1;
|
UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
create procedure test.p1()
|
create procedure test.p1()
|
||||||
begin
|
begin
|
||||||
INSERT INTO test.t1 VALUES(2,'test');
|
INSERT INTO test.t1 VALUES(2,'test');
|
||||||
@ -18,7 +18,7 @@ UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=2;
|
|||||||
end|
|
end|
|
||||||
CALL test.p1();
|
CALL test.p1();
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
SELECT * FROM test.t1 ORDER BY blob_column;
|
SELECT * FROM test.t1 ORDER BY blob_column;
|
||||||
a blob_column
|
a blob_column
|
||||||
1 abase
|
1 abase
|
||||||
|
@ -16,6 +16,10 @@ CREATE TABLE t_self_logging (a VARCHAR(100)) ENGINE = NDB;
|
|||||||
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
|
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
|
||||||
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
||||||
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
|
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
|
||||||
|
CREATE TABLE t_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
|
||||||
|
CREATE TABLE t_double_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
|
||||||
|
CREATE TRIGGER trig_autoinc BEFORE INSERT ON t_autoinc FOR EACH ROW BEGIN INSERT INTO t_stmt VALUES ('x'); END;
|
||||||
|
CREATE TRIGGER trig_double_autoinc BEFORE INSERT ON t_double_autoinc FOR EACH ROW BEGIN INSERT INTO t_autoinc VALUES (NULL); END;
|
||||||
CREATE DATABASE other;
|
CREATE DATABASE other;
|
||||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||||
[on slave]
|
[on slave]
|
||||||
@ -64,8 +68,10 @@ SET @@global.binlog_format = MIXED;
|
|||||||
SET @@session.binlog_format = MIXED;
|
SET @@session.binlog_format = MIXED;
|
||||||
* Unsafe statement and stmt-only engine
|
* Unsafe statement and stmt-only engine
|
||||||
INSERT INTO t_stmt VALUES (UUID());
|
INSERT INTO t_stmt VALUES (UUID());
|
||||||
Warnings:
|
ERROR HY000: Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
Note 1641 Unsafe statement binlogged as statement since storage engine is limited to statement-logging. Reason: Statement uses a system function whose value may differ on slave.
|
* Multi-unsafe statement and stmt-only engine
|
||||||
|
INSERT DELAYED INTO t_double_autoinc SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1;
|
||||||
|
ERROR HY000: Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
|
||||||
---- binlog_format=statement ----
|
---- binlog_format=statement ----
|
||||||
[on slave]
|
[on slave]
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
@ -102,7 +108,7 @@ USE test;
|
|||||||
* Unsafe statement and binlog_format=statement
|
* Unsafe statement and binlog_format=statement
|
||||||
INSERT INTO t VALUES (UUID());
|
INSERT INTO t VALUES (UUID());
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
|
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
|
||||||
* Same statement, but db filtered out - no message
|
* Same statement, but db filtered out - no message
|
||||||
USE other;
|
USE other;
|
||||||
INSERT INTO test.t VALUES (UUID());
|
INSERT INTO test.t VALUES (UUID());
|
||||||
@ -119,7 +125,7 @@ set global sql_slave_skip_counter=1;
|
|||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
[on master]
|
[on master]
|
||||||
==== Clean up ====
|
==== Clean up ====
|
||||||
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt;
|
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt, t_autoinc, t_double_autoinc;
|
||||||
DROP DATABASE other;
|
DROP DATABASE other;
|
||||||
SET @@global.binlog_format = @old_binlog_format;
|
SET @@global.binlog_format = @old_binlog_format;
|
||||||
SET @@session.binlog_format = @old_binlog_format;
|
SET @@session.binlog_format = @old_binlog_format;
|
||||||
|
@ -51,6 +51,11 @@ CREATE TABLE t_self_logging (a VARCHAR(100)) ENGINE = NDB;
|
|||||||
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
|
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
|
||||||
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
||||||
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
|
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
|
||||||
|
CREATE TABLE t_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
|
||||||
|
CREATE TABLE t_double_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
|
||||||
|
|
||||||
|
--eval CREATE TRIGGER trig_autoinc BEFORE INSERT ON t_autoinc FOR EACH ROW BEGIN INSERT INTO t_stmt VALUES ('x'); END
|
||||||
|
--eval CREATE TRIGGER trig_double_autoinc BEFORE INSERT ON t_double_autoinc FOR EACH ROW BEGIN INSERT INTO t_autoinc VALUES (NULL); END
|
||||||
|
|
||||||
CREATE DATABASE other;
|
CREATE DATABASE other;
|
||||||
|
|
||||||
@ -127,9 +132,15 @@ SET @@global.binlog_format = MIXED;
|
|||||||
SET @@session.binlog_format = MIXED;
|
SET @@session.binlog_format = MIXED;
|
||||||
|
|
||||||
--echo * Unsafe statement and stmt-only engine
|
--echo * Unsafe statement and stmt-only engine
|
||||||
# This will give a warning.
|
--error ER_BINLOG_UNSAFE_AND_STMT_ENGINE
|
||||||
INSERT INTO t_stmt VALUES (UUID());
|
INSERT INTO t_stmt VALUES (UUID());
|
||||||
|
|
||||||
|
# Concatenate three unsafe values, and then concatenate NULL to
|
||||||
|
# that so that the result is NULL and we instead use autoinc.
|
||||||
|
--echo * Multi-unsafe statement and stmt-only engine
|
||||||
|
--error ER_BINLOG_UNSAFE_AND_STMT_ENGINE
|
||||||
|
INSERT DELAYED INTO t_double_autoinc SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1;
|
||||||
|
|
||||||
|
|
||||||
--echo ---- binlog_format=statement ----
|
--echo ---- binlog_format=statement ----
|
||||||
|
|
||||||
@ -213,7 +224,7 @@ INSERT INTO t VALUES (UUID());
|
|||||||
|
|
||||||
--echo ==== Clean up ====
|
--echo ==== Clean up ====
|
||||||
|
|
||||||
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt;
|
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt, t_autoinc, t_double_autoinc;
|
||||||
DROP DATABASE other;
|
DROP DATABASE other;
|
||||||
SET @@global.binlog_format = @old_binlog_format;
|
SET @@global.binlog_format = @old_binlog_format;
|
||||||
SET @@session.binlog_format = @old_binlog_format;
|
SET @@session.binlog_format = @old_binlog_format;
|
||||||
|
@ -6076,7 +6076,7 @@ ER_SLAVE_INCIDENT
|
|||||||
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
|
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
|
||||||
eng "Table has no partition for some existing values"
|
eng "Table has no partition for some existing values"
|
||||||
ER_BINLOG_UNSAFE_STATEMENT
|
ER_BINLOG_UNSAFE_STATEMENT
|
||||||
eng "Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT."
|
eng "Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: %s"
|
||||||
ER_SLAVE_FATAL_ERROR
|
ER_SLAVE_FATAL_ERROR
|
||||||
eng "Fatal error: %s"
|
eng "Fatal error: %s"
|
||||||
ER_SLAVE_RELAY_LOG_READ_FAILURE
|
ER_SLAVE_RELAY_LOG_READ_FAILURE
|
||||||
@ -6211,7 +6211,7 @@ ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE
|
|||||||
ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
|
ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
|
||||||
eng "Cannot execute statement: binlogging impossible since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-logging."
|
eng "Cannot execute statement: binlogging impossible since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-logging."
|
||||||
ER_BINLOG_UNSAFE_AND_STMT_ENGINE
|
ER_BINLOG_UNSAFE_AND_STMT_ENGINE
|
||||||
eng "Unsafe statement binlogged as statement since storage engine is limited to statement-logging."
|
eng "Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: %s"
|
||||||
ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE
|
ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE
|
||||||
eng "Cannot execute row injection: binlogging impossible since at least one table uses a storage engine limited to statement-logging."
|
eng "Cannot execute row injection: binlogging impossible since at least one table uses a storage engine limited to statement-logging."
|
||||||
ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
|
ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
|
||||||
@ -6236,7 +6236,5 @@ ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
|
|||||||
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
|
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
|
||||||
eng "Statement uses a system function whose value may differ on slave."
|
eng "Statement uses a system function whose value may differ on slave."
|
||||||
|
|
||||||
ER_BINLOG_UNSAFE_WARNING_SHORT
|
ER_MESSAGE_AND_STATEMENT
|
||||||
eng "%s Reason: %s"
|
eng "%s Statement: %s"
|
||||||
ER_BINLOG_UNSAFE_WARNING_LONG
|
|
||||||
eng "%s Reason: %s Statement: %s"
|
|
||||||
|
@ -3282,8 +3282,8 @@ void xid_cache_delete(XID_STATE *xid_state)
|
|||||||
|
|
||||||
binlog_format * SMRSMRSMR SMRSMRSMR SMRSMRSMR
|
binlog_format * SMRSMRSMR SMRSMRSMR SMRSMRSMR
|
||||||
|
|
||||||
Logged format - SS-SS---- -RR-RR-RR SRRSRR-RR
|
Logged format - SS-S----- -RR-RR-RR SRRSRR-RR
|
||||||
Warning/Error 1 --2332444 5--5--6-- ---7--6--
|
Warning/Error 1 --2732444 5--5--6-- ---7--6--
|
||||||
|
|
||||||
Legend
|
Legend
|
||||||
------
|
------
|
||||||
@ -3303,8 +3303,9 @@ void xid_cache_delete(XID_STATE *xid_state)
|
|||||||
BINLOG_FORMAT = ROW and at least one table uses a storage engine
|
BINLOG_FORMAT = ROW and at least one table uses a storage engine
|
||||||
limited to statement-logging.
|
limited to statement-logging.
|
||||||
|
|
||||||
3. Warning: Unsafe statement binlogged as statement since storage
|
3. Error: Cannot execute statement: binlogging of unsafe statement
|
||||||
engine is limited to statement-logging.
|
is impossible when storage engine is limited to statement-logging
|
||||||
|
and BINLOG_FORMAT = MIXED.
|
||||||
|
|
||||||
4. Error: Cannot execute row injection: binlogging impossible since
|
4. Error: Cannot execute row injection: binlogging impossible since
|
||||||
at least one table uses a storage engine limited to
|
at least one table uses a storage engine limited to
|
||||||
@ -3457,17 +3458,16 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
else if ((unsafe_flags= lex->get_stmt_unsafe_flags()) != 0)
|
else if ((unsafe_flags= lex->get_stmt_unsafe_flags()) != 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
3. Warning: Unsafe statement binlogged as statement since
|
3. Error: Cannot execute statement: binlogging of unsafe
|
||||||
storage engine is limited to statement-logging.
|
statement is impossible when storage engine is limited to
|
||||||
|
statement-logging and BINLOG_FORMAT = MIXED.
|
||||||
*/
|
*/
|
||||||
binlog_unsafe_warning_flags|=
|
for (int unsafe_type= 0;
|
||||||
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE) |
|
unsafe_type < LEX::BINLOG_STMT_UNSAFE_COUNT;
|
||||||
(unsafe_flags << BINLOG_STMT_WARNING_COUNT);
|
unsafe_type++)
|
||||||
DBUG_PRINT("info", ("Scheduling warning to be issued by "
|
if (unsafe_flags & (1 << unsafe_type))
|
||||||
"binlog_query: %s",
|
my_error((error= ER_BINLOG_UNSAFE_AND_STMT_ENGINE), MYF(0),
|
||||||
ER(ER_BINLOG_UNSAFE_AND_STMT_ENGINE)));
|
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||||
DBUG_PRINT("info", ("binlog_unsafe_warning_flags: 0x%x",
|
|
||||||
binlog_unsafe_warning_flags));
|
|
||||||
}
|
}
|
||||||
/* log in statement format! */
|
/* log in statement format! */
|
||||||
}
|
}
|
||||||
@ -3499,13 +3499,11 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
7. Warning: Unsafe statement logged as statement due to
|
7. Warning: Unsafe statement logged as statement due to
|
||||||
binlog_format = STATEMENT
|
binlog_format = STATEMENT
|
||||||
*/
|
*/
|
||||||
binlog_unsafe_warning_flags|=
|
binlog_unsafe_warning_flags|= unsafe_flags;
|
||||||
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE) |
|
|
||||||
(unsafe_flags << BINLOG_STMT_WARNING_COUNT);
|
|
||||||
DBUG_PRINT("info", ("Scheduling warning to be issued by "
|
DBUG_PRINT("info", ("Scheduling warning to be issued by "
|
||||||
"binlog_query: '%s'",
|
"binlog_query: '%s'",
|
||||||
ER(ER_BINLOG_UNSAFE_STATEMENT)));
|
ER(ER_BINLOG_UNSAFE_STATEMENT)));
|
||||||
DBUG_PRINT("info", ("binlog_stmt_flags: 0x%x",
|
DBUG_PRINT("info", ("binlog_unsafe_warning_flags: 0x%x",
|
||||||
binlog_unsafe_warning_flags));
|
binlog_unsafe_warning_flags));
|
||||||
}
|
}
|
||||||
/* log in statement format! */
|
/* log in statement format! */
|
||||||
@ -3536,7 +3534,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
DBUG_PRINT("info", ("decision: no logging since "
|
DBUG_PRINT("info", ("decision: no logging since "
|
||||||
"mysql_bin_log.is_open() = %d "
|
"mysql_bin_log.is_open() = %d "
|
||||||
"and (options & OPTION_BIN_LOG) = 0x%llx "
|
"and (options & OPTION_BIN_LOG) = 0x%llx "
|
||||||
"and binlog_format = %d "
|
"and binlog_format = %ld "
|
||||||
"and binlog_filter->db_ok(db) = %d",
|
"and binlog_filter->db_ok(db) = %d",
|
||||||
mysql_bin_log.is_open(),
|
mysql_bin_log.is_open(),
|
||||||
(options & OPTION_BIN_LOG),
|
(options & OPTION_BIN_LOG),
|
||||||
@ -4037,31 +4035,11 @@ void THD::issue_unsafe_warnings()
|
|||||||
Ensure that binlog_unsafe_warning_flags is big enough to hold all
|
Ensure that binlog_unsafe_warning_flags is big enough to hold all
|
||||||
bits. This is actually a constant expression.
|
bits. This is actually a constant expression.
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(BINLOG_STMT_WARNING_COUNT + 2 * LEX::BINLOG_STMT_UNSAFE_COUNT <=
|
DBUG_ASSERT(2 * LEX::BINLOG_STMT_UNSAFE_COUNT <=
|
||||||
sizeof(binlog_unsafe_warning_flags) * CHAR_BIT);
|
sizeof(binlog_unsafe_warning_flags) * CHAR_BIT);
|
||||||
|
|
||||||
/**
|
uint32 unsafe_type_flags= binlog_unsafe_warning_flags;
|
||||||
@note The order of the elements of this array must correspond to
|
|
||||||
the order of elements in enum_binlog_stmt_unsafe.
|
|
||||||
*/
|
|
||||||
static const int explanations[LEX::BINLOG_STMT_UNSAFE_COUNT] =
|
|
||||||
{
|
|
||||||
ER_BINLOG_UNSAFE_LIMIT,
|
|
||||||
ER_BINLOG_UNSAFE_INSERT_DELAYED,
|
|
||||||
ER_BINLOG_UNSAFE_SYSTEM_TABLE,
|
|
||||||
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS,
|
|
||||||
ER_BINLOG_UNSAFE_UDF,
|
|
||||||
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
|
|
||||||
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
|
|
||||||
};
|
|
||||||
uint32 flags= binlog_unsafe_warning_flags;
|
|
||||||
/* No warnings (yet) for this statement. */
|
|
||||||
if (flags == 0)
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
|
|
||||||
/* Get the types of unsafeness that affect the current statement. */
|
|
||||||
uint32 unsafe_type_flags= flags >> BINLOG_STMT_WARNING_COUNT;
|
|
||||||
DBUG_ASSERT((unsafe_type_flags & LEX::BINLOG_STMT_UNSAFE_ALL_FLAGS) != 0);
|
|
||||||
/*
|
/*
|
||||||
Clear: (1) bits above BINLOG_STMT_UNSAFE_COUNT; (2) bits for
|
Clear: (1) bits above BINLOG_STMT_UNSAFE_COUNT; (2) bits for
|
||||||
warnings that have been printed already.
|
warnings that have been printed already.
|
||||||
@ -4072,18 +4050,7 @@ void THD::issue_unsafe_warnings()
|
|||||||
if (unsafe_type_flags == 0)
|
if (unsafe_type_flags == 0)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
/* Figure out which error code to issue. */
|
DBUG_PRINT("info", ("unsafe_type_flags: 0x%x", unsafe_type_flags));
|
||||||
int err;
|
|
||||||
if (binlog_unsafe_warning_flags &
|
|
||||||
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE))
|
|
||||||
err= ER_BINLOG_UNSAFE_AND_STMT_ENGINE;
|
|
||||||
else {
|
|
||||||
DBUG_ASSERT(binlog_unsafe_warning_flags &
|
|
||||||
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE));
|
|
||||||
err= ER_BINLOG_UNSAFE_STATEMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("flags: 0x%x err: %d", unsafe_type_flags, err));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For each unsafe_type, check if the statement is unsafe in this way
|
For each unsafe_type, check if the statement is unsafe in this way
|
||||||
@ -4095,20 +4062,25 @@ void THD::issue_unsafe_warnings()
|
|||||||
{
|
{
|
||||||
if ((unsafe_type_flags & (1 << unsafe_type)) != 0)
|
if ((unsafe_type_flags & (1 << unsafe_type)) != 0)
|
||||||
{
|
{
|
||||||
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE, err,
|
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER(ER_BINLOG_UNSAFE_WARNING_SHORT),
|
ER_BINLOG_UNSAFE_STATEMENT,
|
||||||
ER(err), ER(explanations[unsafe_type]));
|
ER(ER_BINLOG_UNSAFE_STATEMENT),
|
||||||
|
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||||
if (global_system_variables.log_warnings)
|
if (global_system_variables.log_warnings)
|
||||||
sql_print_warning(ER(ER_BINLOG_UNSAFE_WARNING_LONG),
|
{
|
||||||
ER(err), ER(explanations[unsafe_type]), query);
|
char buf[MYSQL_ERRMSG_SIZE * 2];
|
||||||
|
sprintf(buf, ER(ER_BINLOG_UNSAFE_STATEMENT),
|
||||||
|
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||||
|
sql_print_warning(ER(ER_MESSAGE_AND_STATEMENT), buf, query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Mark these unsafe types as already printed, to avoid printing
|
Mark these unsafe types as already printed, to avoid printing
|
||||||
warnings for them again.
|
warnings for them again.
|
||||||
*/
|
*/
|
||||||
binlog_unsafe_warning_flags|= unsafe_type_flags <<
|
binlog_unsafe_warning_flags|=
|
||||||
(BINLOG_STMT_WARNING_COUNT + LEX::BINLOG_STMT_UNSAFE_COUNT);
|
unsafe_type_flags << LEX::BINLOG_STMT_UNSAFE_COUNT;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,42 +1449,21 @@ private:
|
|||||||
*/
|
*/
|
||||||
enum_binlog_format current_stmt_binlog_format;
|
enum_binlog_format current_stmt_binlog_format;
|
||||||
|
|
||||||
/**
|
|
||||||
Enumeration listing binlog-related warnings that a statement can
|
|
||||||
cause.
|
|
||||||
*/
|
|
||||||
enum enum_binlog_stmt_warning {
|
|
||||||
|
|
||||||
/* ER_BINLOG_UNSAFE_AND_STMT_ENGINE affects current stmt */
|
|
||||||
BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE= 0,
|
|
||||||
|
|
||||||
/* ER_BINLOG_UNSAFE_STATEMENT affects current stmt */
|
|
||||||
BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE,
|
|
||||||
|
|
||||||
/** The last element of this enumeration type. */
|
|
||||||
BINLOG_STMT_WARNING_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Bit field for the state of binlog warnings.
|
Bit field for the state of binlog warnings.
|
||||||
|
|
||||||
There are three groups of bits:
|
There are two groups of bits:
|
||||||
|
|
||||||
- The low BINLOG_STMT_WARNING_COUNT bits indicate the type of
|
- The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
|
||||||
warning that the current (top-level) statement will issue. At
|
unsafeness that the current statement has.
|
||||||
most one of these bits should be set (this is ensured by the
|
|
||||||
logic in decide_logging_format).
|
|
||||||
|
|
||||||
- The following Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types
|
|
||||||
of unsafeness that the current statement has.
|
|
||||||
|
|
||||||
- The following Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types
|
- The following Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types
|
||||||
of unsafeness that the current statement has issued warnings
|
of unsafeness that the current statement has issued warnings
|
||||||
for.
|
for.
|
||||||
|
|
||||||
Hence, this variable must be big enough to hold
|
Hence, this variable must be big enough to hold
|
||||||
BINLOG_STMT_WARNING_COUNT + 2 * Lex::BINLOG_STMT_UNSAFE_COUNT
|
2*Lex::BINLOG_STMT_UNSAFE_COUNT bits. This is asserted in @c
|
||||||
bits. This is asserted in @c issue_unsafe_warnings().
|
issue_unsafe_warnings().
|
||||||
|
|
||||||
The first and second groups of bits are set by @c
|
The first and second groups of bits are set by @c
|
||||||
decide_logging_format() when it detects that a warning should be
|
decide_logging_format() when it detects that a warning should be
|
||||||
|
@ -31,6 +31,23 @@
|
|||||||
|
|
||||||
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
|
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@note The order of the elements of this array must correspond to
|
||||||
|
the order of elements in enum_binlog_stmt_unsafe.
|
||||||
|
*/
|
||||||
|
const int
|
||||||
|
Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
|
||||||
|
{
|
||||||
|
ER_BINLOG_UNSAFE_LIMIT,
|
||||||
|
ER_BINLOG_UNSAFE_INSERT_DELAYED,
|
||||||
|
ER_BINLOG_UNSAFE_SYSTEM_TABLE,
|
||||||
|
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS,
|
||||||
|
ER_BINLOG_UNSAFE_UDF,
|
||||||
|
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
|
||||||
|
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Longest standard keyword name */
|
/* Longest standard keyword name */
|
||||||
#define TOCK_NAME_LENGTH 24
|
#define TOCK_NAME_LENGTH 24
|
||||||
|
|
||||||
|
@ -1099,6 +1099,11 @@ public:
|
|||||||
static const int BINLOG_STMT_UNSAFE_ALL_FLAGS=
|
static const int BINLOG_STMT_UNSAFE_ALL_FLAGS=
|
||||||
((1 << BINLOG_STMT_UNSAFE_COUNT) - 1);
|
((1 << BINLOG_STMT_UNSAFE_COUNT) - 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maps elements of enum_binlog_stmt_unsafe to error codes.
|
||||||
|
*/
|
||||||
|
static const int binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Determine if this statement is marked as unsafe.
|
Determine if this statement is marked as unsafe.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user