Skip to content

Commit ed70ee5

Browse files
committed
WL#8993: Option to not log in the error log when unsafe statements are executed whilst using STATEMENT based binary logging
Added a log_statements_unsafe_for_binlog option, which purely disables writing the unsafe statement warnings to the error log (warnings are still sent to the clients). Reviewed-by: Joao Gramacho <[email protected]> Reviewed-by: Luis Soares <[email protected]> RB: 11076
1 parent 177fb41 commit ed70ee5

11 files changed

+298
-1
lines changed

mysql-test/r/mysqld--help-notwin.result

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ The following options may be given as the first argument:
415415
--log-slow-slave-statements
416416
Log slow statements executed by slave thread to the slow
417417
log if it is open.
418+
--log-statements-unsafe-for-binlog
419+
Log statements considered unsafe when using statement
420+
based binary logging.
421+
(Defaults to on; use --skip-log-statements-unsafe-for-binlog to disable.)
418422
--log-syslog Errors, warnings, and similar issues eligible for MySQL's
419423
error log file may additionally be sent to the host
420424
operating system's system log ("syslog").
@@ -1331,6 +1335,7 @@ log-short-format FALSE
13311335
log-slave-updates FALSE
13321336
log-slow-admin-statements FALSE
13331337
log-slow-slave-statements FALSE
1338+
log-statements-unsafe-for-binlog TRUE
13341339
log-syslog FALSE
13351340
log-syslog-facility daemon
13361341
log-syslog-include-pid TRUE

mysql-test/r/mysqld--help-win.result

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ The following options may be given as the first argument:
413413
--log-slow-slave-statements
414414
Log slow statements executed by slave thread to the slow
415415
log if it is open.
416+
--log-statements-unsafe-for-binlog
417+
Log statements considered unsafe when using statement
418+
based binary logging.
419+
(Defaults to on; use --skip-log-statements-unsafe-for-binlog to disable.)
416420
--log-syslog Errors, warnings, and similar issues eligible for MySQL's
417421
error log file may additionally be sent to the host
418422
operating system's system log ("syslog").
@@ -1328,6 +1332,7 @@ log-short-format FALSE
13281332
log-slave-updates FALSE
13291333
log-slow-admin-statements FALSE
13301334
log-slow-slave-statements FALSE
1335+
log-statements-unsafe-for-binlog TRUE
13311336
log-syslog FALSE
13321337
log-syslog-tag
13331338
log-tc tc.log
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# restart
2+
CALL mtr.add_suppression("Unsafe statement written to the binary log");
3+
CREATE TABLE test.unsafe (i int auto_increment primary key, j int) engine = innodb;
4+
INSERT INTO test.unsafe (j) VALUES (1), (2), (3);
5+
SCENARIO 1
6+
SET GLOBAL log_statements_unsafe_for_binlog= ON;
7+
UPDATE test.unsafe SET j = 4 LIMIT 1;
8+
Warnings:
9+
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
10+
include/assert_grep.inc [Exactly one row should be written to the error log.]
11+
SCENARIO 2
12+
SET GLOBAL log_statements_unsafe_for_binlog= OFF;
13+
UPDATE test.unsafe SET j = 4 LIMIT 1;
14+
Warnings:
15+
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
16+
DROP TABLE test.unsafe;
17+
SET GLOBAL log_statements_unsafe_for_binlog= 1;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# ==== Purpose ====
2+
#
3+
# Verify that the log_statements_unsafe_for_binlog system variable works
4+
#
5+
# ==== Method ====
6+
#
7+
# 1. Turn on log_statements_unsafe_for_binlog
8+
# 2. Run unsafe statement
9+
# 3. Verify error log contains warning
10+
# 4. Turn off log_statements_unsafe_for_binlog
11+
# 5. Run unsafe statement
12+
# 6. Verify error log still contains only one warning
13+
#
14+
# ==== References ====
15+
#
16+
# WL#8993: Option to not log in the error log when unsafe statements are executed whilst using STATEMENT based binary logging
17+
18+
--source include/have_log_bin.inc
19+
--source include/have_binlog_format_statement.inc
20+
21+
# As this test file will check for information on the error log, we will
22+
# restart the server to make sure that the log contains an "startup" log
23+
# message to be used as starting point for the grep.
24+
--source include/restart_mysqld.inc
25+
26+
CALL mtr.add_suppression("Unsafe statement written to the binary log");
27+
28+
# Setup
29+
--let $saved_lsufb= `SELECT @@GLOBAL.log_statements_unsafe_for_binlog`
30+
31+
CREATE TABLE test.unsafe (i int auto_increment primary key, j int) engine = innodb;
32+
33+
INSERT INTO test.unsafe (j) VALUES (1), (2), (3);
34+
35+
#
36+
# SCENARIO 1:
37+
#
38+
# Assert that unsafe statements are written when the option is ON (default)
39+
#
40+
--echo SCENARIO 1
41+
SET GLOBAL log_statements_unsafe_for_binlog= ON;
42+
43+
UPDATE test.unsafe SET j = 4 LIMIT 1;
44+
45+
# File to GREP
46+
--let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.1.err
47+
# Show entries only after the last occurrence of the following pattern
48+
--let $assert_only_after=.* \[Note\] .* ready for connections
49+
--let $assert_select=.* \[Warning\] Unsafe statement written to the binary log
50+
--let $assert_text= Exactly one row should be written to the error log.
51+
--let $assert_count= 1
52+
--source include/assert_grep.inc
53+
54+
#
55+
# SCENARIO 2:
56+
# Assert that unsafe statements are NOT written when the option is OFF
57+
#
58+
--echo SCENARIO 2
59+
SET GLOBAL log_statements_unsafe_for_binlog= OFF;
60+
61+
connect (conn1,localhost,root,,);
62+
63+
connection conn1;
64+
65+
UPDATE test.unsafe SET j = 4 LIMIT 1;
66+
67+
let $assert_text= Still only one row should be present in the error log.
68+
--let $assert_count= 1
69+
--source include/assert_grep.inc
70+
71+
# Clean up
72+
disconnect conn1;
73+
DROP TABLE test.unsafe;
74+
--eval SET GLOBAL log_statements_unsafe_for_binlog= $saved_lsufb

mysql-test/suite/perfschema/r/show_sanity.result

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ where show_mode = "JUNK: GLOBAL-ONLY"
408408
order by show_mode, source, variable_name;
409409
SHOW_MODE SOURCE VARIABLE_NAME
410410
5.6 I_S.SESSION_VARIABLES GTID_EXECUTED
411+
5.6 I_S.SESSION_VARIABLES LOG_STATEMENTS_UNSAFE_FOR_BINLOG
411412
5.6 I_S.SESSION_VARIABLES TLS_VERSION
412413

413414
================================================================================
@@ -430,6 +431,7 @@ where show_mode = "JUNK: GLOBAL-ONLY"
430431
order by show_mode, source, variable_name;
431432
SHOW_MODE SOURCE VARIABLE_NAME
432433
5.6 I_S.SESSION_VARIABLES GTID_EXECUTED
434+
5.6 I_S.SESSION_VARIABLES LOG_STATEMENTS_UNSAFE_FOR_BINLOG
433435
5.6 I_S.SESSION_VARIABLES TLS_VERSION
434436

435437
================================================================================
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
SET @start_value= @@global.log_statements_unsafe_for_binlog;
2+
SET @@global.log_statements_unsafe_for_binlog= DEFAULT;
3+
SELECT @@global.log_statements_unsafe_for_binlog;
4+
@@global.log_statements_unsafe_for_binlog
5+
1
6+
SET @@global.log_statements_unsafe_for_binlog= TRUE;
7+
SELECT @@global.log_statements_unsafe_for_binlog;
8+
@@global.log_statements_unsafe_for_binlog
9+
1
10+
SET @@global.log_statements_unsafe_for_binlog= true;
11+
SELECT @@global.log_statements_unsafe_for_binlog;
12+
@@global.log_statements_unsafe_for_binlog
13+
1
14+
SET @@global.log_statements_unsafe_for_binlog= 0;
15+
SELECT @@global.log_statements_unsafe_for_binlog;
16+
@@global.log_statements_unsafe_for_binlog
17+
0
18+
SET @@global.log_statements_unsafe_for_binlog= 1;
19+
SELECT @@global.log_statements_unsafe_for_binlog;
20+
@@global.log_statements_unsafe_for_binlog
21+
1
22+
SET @goodvar= TRUE;
23+
SET @@global.log_statements_unsafe_for_binlog= @goodvar;
24+
SELECT @@global.log_statements_unsafe_for_binlog;
25+
@@global.log_statements_unsafe_for_binlog
26+
1
27+
SET GLOBAL log_statements_unsafe_for_binlog= DEFAULT;
28+
SELECT @@global.log_statements_unsafe_for_binlog;
29+
@@global.log_statements_unsafe_for_binlog
30+
1
31+
SET GLOBAL log_statements_unsafe_for_binlog= ON;
32+
SELECT @@global.log_statements_unsafe_for_binlog;
33+
@@global.log_statements_unsafe_for_binlog
34+
1
35+
SET GLOBAL log_statements_unsafe_for_binlog= OFF;
36+
SELECT @@global.log_statements_unsafe_for_binlog;
37+
@@global.log_statements_unsafe_for_binlog
38+
0
39+
SET GLOBAL log_statements_unsafe_for_binlog= -0;
40+
SELECT @@global.log_statements_unsafe_for_binlog;
41+
@@global.log_statements_unsafe_for_binlog
42+
0
43+
SET GLOBAL log_statements_unsafe_for_binlog= 0.00;
44+
ERROR 42000: Incorrect argument type to variable 'log_statements_unsafe_for_binlog'
45+
SET GLOBAL log_statements_unsafe_for_binlog= +0;
46+
SELECT @@global.log_statements_unsafe_for_binlog;
47+
@@global.log_statements_unsafe_for_binlog
48+
0
49+
SET @@global.log_statements_unsafe_for_binlog= 'DEFAULT';
50+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of 'DEFAULT'
51+
SET @@global.log_statements_unsafe_for_binlog= 'true';
52+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of 'true'
53+
SET @@global.log_statements_unsafe_for_binlog= BLABLA;
54+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of 'BLABLA'
55+
SET @@global.log_statements_unsafe_for_binlog= 25;
56+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of '25'
57+
SET GLOBAL log_statements_unsafe_for_binlog= -1;
58+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of '-1'
59+
SET @badvar= 'true';
60+
SET @@global.log_statements_unsafe_for_binlog= @badvar;
61+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of 'true'
62+
SET GLOBAL log_statements_unsafe_for_binlog= 'DEFAULT';
63+
ERROR 42000: Variable 'log_statements_unsafe_for_binlog' can't be set to the value of 'DEFAULT'
64+
SET log_statements_unsafe_for_binlog= TRUE;
65+
ERROR HY000: Variable 'log_statements_unsafe_for_binlog' is a GLOBAL variable and should be set with SET GLOBAL
66+
SET SESSION log_statements_unsafe_for_binlog= TRUE;
67+
ERROR HY000: Variable 'log_statements_unsafe_for_binlog' is a GLOBAL variable and should be set with SET GLOBAL
68+
SET @@session.log_statements_unsafe_for_binlog= TRUE;
69+
ERROR HY000: Variable 'log_statements_unsafe_for_binlog' is a GLOBAL variable and should be set with SET GLOBAL
70+
SET LOCAL log_statements_unsafe_for_binlog= TRUE;
71+
ERROR HY000: Variable 'log_statements_unsafe_for_binlog' is a GLOBAL variable and should be set with SET GLOBAL
72+
SET @@global log_statements_unsafe_for_binlog= TRUE;
73+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'log_statements_unsafe_for_binlog= TRUE' at line 1
74+
SET @@SESSION log_statements_unsafe_for_binlog= TRUE;
75+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'log_statements_unsafe_for_binlog= TRUE' at line 1
76+
SET @@global.log_statements_unsafe_for_binlog= @start_value;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
################## mysql-test\t\log_statements_unsafe_for_binlog.test #########
2+
# #
3+
# Variable Name: log_statements_unsafe_for_binlog #
4+
# Scope: Global #
5+
# Access Type: Static #
6+
# Data Type: Boolean #
7+
# #
8+
# #
9+
# Creation Date: 2015-11-19 #
10+
# Author : Mark Leith #
11+
# #
12+
# Description:Test Cases of Dynamic System Variable #
13+
# log_statements_unsafe_for_binlog #
14+
# that checks the behavior of this variable in the following ways #
15+
# * Value Check #
16+
# * Scope Check #
17+
# #
18+
# Reference: #
19+
# http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html #
20+
# #
21+
###############################################################################
22+
23+
SET @start_value= @@global.log_statements_unsafe_for_binlog;
24+
25+
####################################################################
26+
# Valid values for boolean #
27+
####################################################################
28+
SET @@global.log_statements_unsafe_for_binlog= DEFAULT;
29+
SELECT @@global.log_statements_unsafe_for_binlog;
30+
31+
SET @@global.log_statements_unsafe_for_binlog= TRUE;
32+
SELECT @@global.log_statements_unsafe_for_binlog;
33+
34+
SET @@global.log_statements_unsafe_for_binlog= true;
35+
SELECT @@global.log_statements_unsafe_for_binlog;
36+
37+
SET @@global.log_statements_unsafe_for_binlog= 0;
38+
SELECT @@global.log_statements_unsafe_for_binlog;
39+
40+
SET @@global.log_statements_unsafe_for_binlog= 1;
41+
SELECT @@global.log_statements_unsafe_for_binlog;
42+
43+
SET @goodvar= TRUE;
44+
SET @@global.log_statements_unsafe_for_binlog= @goodvar;
45+
SELECT @@global.log_statements_unsafe_for_binlog;
46+
47+
SET GLOBAL log_statements_unsafe_for_binlog= DEFAULT;
48+
SELECT @@global.log_statements_unsafe_for_binlog;
49+
50+
SET GLOBAL log_statements_unsafe_for_binlog= ON;
51+
SELECT @@global.log_statements_unsafe_for_binlog;
52+
53+
SET GLOBAL log_statements_unsafe_for_binlog= OFF;
54+
SELECT @@global.log_statements_unsafe_for_binlog;
55+
56+
SET GLOBAL log_statements_unsafe_for_binlog= -0;
57+
SELECT @@global.log_statements_unsafe_for_binlog;
58+
59+
--error ER_WRONG_TYPE_FOR_VAR
60+
SET GLOBAL log_statements_unsafe_for_binlog= 0.00;
61+
62+
SET GLOBAL log_statements_unsafe_for_binlog= +0;
63+
SELECT @@global.log_statements_unsafe_for_binlog;
64+
65+
#################################################################
66+
# Check if the value in GLOBAL Table matches value in variable #
67+
#################################################################
68+
69+
--error ER_WRONG_VALUE_FOR_VAR
70+
SET @@global.log_statements_unsafe_for_binlog= 'DEFAULT';
71+
72+
--error ER_WRONG_VALUE_FOR_VAR
73+
SET @@global.log_statements_unsafe_for_binlog= 'true';
74+
75+
--error ER_WRONG_VALUE_FOR_VAR
76+
SET @@global.log_statements_unsafe_for_binlog= BLABLA;
77+
78+
--error ER_WRONG_VALUE_FOR_VAR
79+
SET @@global.log_statements_unsafe_for_binlog= 25;
80+
81+
--error ER_WRONG_VALUE_FOR_VAR
82+
SET GLOBAL log_statements_unsafe_for_binlog= -1;
83+
84+
SET @badvar= 'true';
85+
--error ER_WRONG_VALUE_FOR_VAR
86+
SET @@global.log_statements_unsafe_for_binlog= @badvar;
87+
88+
--error ER_WRONG_VALUE_FOR_VAR
89+
SET GLOBAL log_statements_unsafe_for_binlog= 'DEFAULT';
90+
91+
--error ER_GLOBAL_VARIABLE
92+
SET log_statements_unsafe_for_binlog= TRUE;
93+
94+
--error ER_GLOBAL_VARIABLE
95+
SET SESSION log_statements_unsafe_for_binlog= TRUE;
96+
97+
--error ER_GLOBAL_VARIABLE
98+
SET @@session.log_statements_unsafe_for_binlog= TRUE;
99+
100+
--error ER_GLOBAL_VARIABLE
101+
SET LOCAL log_statements_unsafe_for_binlog= TRUE;
102+
103+
--error ER_PARSE_ERROR
104+
SET @@global log_statements_unsafe_for_binlog= TRUE;
105+
106+
--error ER_PARSE_ERROR
107+
SET @@SESSION log_statements_unsafe_for_binlog= TRUE;
108+
109+
SET @@global.log_statements_unsafe_for_binlog= @start_value;
110+

sql/binlog.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11143,7 +11143,7 @@ void THD::issue_unsafe_warnings()
1114311143
ER_BINLOG_UNSAFE_STATEMENT,
1114411144
ER(ER_BINLOG_UNSAFE_STATEMENT),
1114511145
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
11146-
if (log_error_verbosity > 1)
11146+
if (log_error_verbosity > 1 && opt_log_unsafe_statements)
1114711147
{
1114811148
if (unsafe_type == LEX::BINLOG_STMT_UNSAFE_LIMIT)
1114911149
do_unsafe_limit_checkout( buf, unsafe_type, query().str);

sql/mysqld.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ my_bool binlog_gtid_simple_recovery;
419419
ulong binlog_error_action;
420420
const char *binlog_error_action_list[]= {"IGNORE_ERROR", "ABORT_SERVER", NullS};
421421
uint32 gtid_executed_compression_period= 0;
422+
my_bool opt_log_unsafe_statements;
422423

423424
#ifdef HAVE_INITGROUPS
424425
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */

sql/mysqld.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ extern MY_BITMAP temp_pool;
121121
extern bool opt_large_files, server_id_supplied;
122122
extern bool opt_update_log, opt_bin_log;
123123
extern my_bool opt_log_slave_updates;
124+
extern my_bool opt_log_unsafe_statements;
124125
extern bool opt_general_log, opt_slow_log, opt_general_log_raw;
125126
extern my_bool opt_backup_history_log;
126127
extern my_bool opt_backup_progress_log;

sql/sys_vars.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,12 @@ static Sys_var_enum Sys_log_timestamps(
20402040
timestamp_type_names, DEFAULT(0),
20412041
NO_MUTEX_GUARD, NOT_IN_BINLOG);
20422042

2043+
static Sys_var_mybool Sys_log_statements_unsafe_for_binlog(
2044+
"log_statements_unsafe_for_binlog",
2045+
"Log statements considered unsafe when using statement based binary logging.",
2046+
GLOBAL_VAR(opt_log_unsafe_statements),
2047+
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
2048+
20432049
/* logging to host OS's syslog */
20442050

20452051
static bool fix_syslog(sys_var *self, THD *thd, enum_var_type type)

0 commit comments

Comments
 (0)