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
|
||||
insert delayed into t1 values (null),(null),(null),(null);
|
||||
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);
|
||||
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;
|
||||
a
|
||||
207
|
||||
|
@ -11,7 +11,7 @@ prepare s from "insert into t1 select 100 limit ?";
|
||||
set @a=100;
|
||||
execute s using @a;
|
||||
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>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
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);
|
||||
UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
|
||||
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;
|
||||
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;
|
||||
### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown
|
||||
SET SQL_LOG_BIN= 0;
|
||||
@ -38,11 +38,11 @@ CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(10));
|
||||
SET GLOBAL LOG_WARNINGS = 0;
|
||||
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
|
||||
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;
|
||||
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
|
||||
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;
|
||||
SET GLOBAL log_warnings = @old_log_warnings;
|
||||
# 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
|
||||
7
|
||||
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: 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 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 system function whose value may differ on slave.
|
||||
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
|
||||
INSERT INTO logtbl VALUES (sect,test,found_rows);
|
||||
END $$
|
||||
|
@ -10,7 +10,7 @@ CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, PRIMARY KEY(a));
|
||||
INSERT INTO test.t1 VALUES(1,'test');
|
||||
UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1;
|
||||
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()
|
||||
begin
|
||||
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|
|
||||
CALL test.p1();
|
||||
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;
|
||||
a blob_column
|
||||
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_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
||||
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;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
[on slave]
|
||||
@ -64,8 +68,10 @@ SET @@global.binlog_format = MIXED;
|
||||
SET @@session.binlog_format = MIXED;
|
||||
* Unsafe statement and stmt-only engine
|
||||
INSERT INTO t_stmt VALUES (UUID());
|
||||
Warnings:
|
||||
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.
|
||||
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.
|
||||
* 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 ----
|
||||
[on slave]
|
||||
include/stop_slave.inc
|
||||
@ -102,7 +108,7 @@ USE test;
|
||||
* Unsafe statement and binlog_format=statement
|
||||
INSERT INTO t VALUES (UUID());
|
||||
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
|
||||
USE other;
|
||||
INSERT INTO test.t VALUES (UUID());
|
||||
@ -119,7 +125,7 @@ set global sql_slave_skip_counter=1;
|
||||
include/start_slave.inc
|
||||
[on master]
|
||||
==== 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;
|
||||
SET @@global.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_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
||||
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;
|
||||
|
||||
@ -127,9 +132,15 @@ SET @@global.binlog_format = MIXED;
|
||||
SET @@session.binlog_format = MIXED;
|
||||
|
||||
--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());
|
||||
|
||||
# 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 ----
|
||||
|
||||
@ -213,7 +224,7 @@ INSERT INTO t VALUES (UUID());
|
||||
|
||||
--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;
|
||||
SET @@global.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
|
||||
eng "Table has no partition for some existing values"
|
||||
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
|
||||
eng "Fatal error: %s"
|
||||
ER_SLAVE_RELAY_LOG_READ_FAILURE
|
||||
@ -6211,7 +6211,7 @@ ER_BINLOG_ROW_ENGINE_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."
|
||||
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
|
||||
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
|
||||
@ -6236,7 +6236,5 @@ ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
|
||||
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
|
||||
eng "Statement uses a system function whose value may differ on slave."
|
||||
|
||||
ER_BINLOG_UNSAFE_WARNING_SHORT
|
||||
eng "%s Reason: %s"
|
||||
ER_BINLOG_UNSAFE_WARNING_LONG
|
||||
eng "%s Reason: %s Statement: %s"
|
||||
ER_MESSAGE_AND_STATEMENT
|
||||
eng "%s Statement: %s"
|
||||
|
@ -3282,8 +3282,8 @@ void xid_cache_delete(XID_STATE *xid_state)
|
||||
|
||||
binlog_format * SMRSMRSMR SMRSMRSMR SMRSMRSMR
|
||||
|
||||
Logged format - SS-SS---- -RR-RR-RR SRRSRR-RR
|
||||
Warning/Error 1 --2332444 5--5--6-- ---7--6--
|
||||
Logged format - SS-S----- -RR-RR-RR SRRSRR-RR
|
||||
Warning/Error 1 --2732444 5--5--6-- ---7--6--
|
||||
|
||||
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
|
||||
limited to statement-logging.
|
||||
|
||||
3. Warning: Unsafe statement binlogged as statement since storage
|
||||
engine is limited to statement-logging.
|
||||
3. Error: Cannot execute statement: binlogging of unsafe statement
|
||||
is impossible when storage engine is limited to statement-logging
|
||||
and BINLOG_FORMAT = MIXED.
|
||||
|
||||
4. Error: Cannot execute row injection: binlogging impossible since
|
||||
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)
|
||||
{
|
||||
/*
|
||||
3. Warning: Unsafe statement binlogged as statement since
|
||||
storage engine is limited to statement-logging.
|
||||
3. Error: Cannot execute statement: binlogging of unsafe
|
||||
statement is impossible when storage engine is limited to
|
||||
statement-logging and BINLOG_FORMAT = MIXED.
|
||||
*/
|
||||
binlog_unsafe_warning_flags|=
|
||||
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE) |
|
||||
(unsafe_flags << BINLOG_STMT_WARNING_COUNT);
|
||||
DBUG_PRINT("info", ("Scheduling warning to be issued by "
|
||||
"binlog_query: %s",
|
||||
ER(ER_BINLOG_UNSAFE_AND_STMT_ENGINE)));
|
||||
DBUG_PRINT("info", ("binlog_unsafe_warning_flags: 0x%x",
|
||||
binlog_unsafe_warning_flags));
|
||||
for (int unsafe_type= 0;
|
||||
unsafe_type < LEX::BINLOG_STMT_UNSAFE_COUNT;
|
||||
unsafe_type++)
|
||||
if (unsafe_flags & (1 << unsafe_type))
|
||||
my_error((error= ER_BINLOG_UNSAFE_AND_STMT_ENGINE), MYF(0),
|
||||
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||
}
|
||||
/* 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
|
||||
binlog_format = STATEMENT
|
||||
*/
|
||||
binlog_unsafe_warning_flags|=
|
||||
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE) |
|
||||
(unsafe_flags << BINLOG_STMT_WARNING_COUNT);
|
||||
binlog_unsafe_warning_flags|= unsafe_flags;
|
||||
DBUG_PRINT("info", ("Scheduling warning to be issued by "
|
||||
"binlog_query: '%s'",
|
||||
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));
|
||||
}
|
||||
/* log in statement format! */
|
||||
@ -3536,7 +3534,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
DBUG_PRINT("info", ("decision: no logging since "
|
||||
"mysql_bin_log.is_open() = %d "
|
||||
"and (options & OPTION_BIN_LOG) = 0x%llx "
|
||||
"and binlog_format = %d "
|
||||
"and binlog_format = %ld "
|
||||
"and binlog_filter->db_ok(db) = %d",
|
||||
mysql_bin_log.is_open(),
|
||||
(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
|
||||
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);
|
||||
|
||||
/**
|
||||
@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;
|
||||
uint32 unsafe_type_flags= binlog_unsafe_warning_flags;
|
||||
|
||||
/* 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
|
||||
warnings that have been printed already.
|
||||
@ -4072,18 +4050,7 @@ void THD::issue_unsafe_warnings()
|
||||
if (unsafe_type_flags == 0)
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
/* Figure out which error code to issue. */
|
||||
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));
|
||||
DBUG_PRINT("info", ("unsafe_type_flags: 0x%x", unsafe_type_flags));
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE, err,
|
||||
ER(ER_BINLOG_UNSAFE_WARNING_SHORT),
|
||||
ER(err), ER(explanations[unsafe_type]));
|
||||
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_BINLOG_UNSAFE_STATEMENT,
|
||||
ER(ER_BINLOG_UNSAFE_STATEMENT),
|
||||
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||
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
|
||||
warnings for them again.
|
||||
*/
|
||||
binlog_unsafe_warning_flags|= unsafe_type_flags <<
|
||||
(BINLOG_STMT_WARNING_COUNT + LEX::BINLOG_STMT_UNSAFE_COUNT);
|
||||
binlog_unsafe_warning_flags|=
|
||||
unsafe_type_flags << LEX::BINLOG_STMT_UNSAFE_COUNT;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -1449,42 +1449,21 @@ private:
|
||||
*/
|
||||
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.
|
||||
|
||||
There are three groups of bits:
|
||||
There are two groups of bits:
|
||||
|
||||
- The low BINLOG_STMT_WARNING_COUNT bits indicate the type of
|
||||
warning that the current (top-level) statement will issue. At
|
||||
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 first 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
|
||||
of unsafeness that the current statement has issued warnings
|
||||
for.
|
||||
|
||||
Hence, this variable must be big enough to hold
|
||||
BINLOG_STMT_WARNING_COUNT + 2 * Lex::BINLOG_STMT_UNSAFE_COUNT
|
||||
bits. This is asserted in @c issue_unsafe_warnings().
|
||||
2*Lex::BINLOG_STMT_UNSAFE_COUNT bits. This is asserted in @c
|
||||
issue_unsafe_warnings().
|
||||
|
||||
The first and second groups of bits are set by @c
|
||||
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;
|
||||
|
||||
/**
|
||||
@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 */
|
||||
#define TOCK_NAME_LENGTH 24
|
||||
|
||||
|
@ -1099,6 +1099,11 @@ public:
|
||||
static const int BINLOG_STMT_UNSAFE_ALL_FLAGS=
|
||||
((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.
|
||||
|
||||
|
Reference in New Issue
Block a user