Skip to content

Commit ae750d6

Browse files
author
Sven Sandberg
committed
WL#7083 step 6.1. GTID-violations: Make ENFORCE_GTID_CONSISTENCY settable, allow WARN.
@sql/rpl_gtid.h, @sql/rpl_gtid_misc.cc - Define the three allowed values for enforce-gtid-consistency. @sql/sys_vars.cc, @sql/sys_vars.h - Make enforce_gtid_consistency settable - Create a new class for enforce_gtid_consistency - Use global_sid_lock.wrlock when changing enforce_gtid_consistency. - Define check_super_outside_trx_outside_sf also when HAVE_REPLICATION is not defined, since enforce_gtid_consistency now uses it. @sql/binlog.cc:handle_gtid_consistency_violation - Implement new logic for when a GTID-violation generates an error/warning. @sql/binlog.cc:is_ddl_gtid_compatible, @sql/binlog.cc:is_dml_gtid_compatible - Use handle_gtid_consistency_violation to determine if an error/warning should be generated. @sql/binlog.cc:decide_logging_format, @sql/rpl_gtid_execution.cc:gtid_pre_statement_checks - Call is_[ddl|dml]_gtid_compatible regardless of enforce_gtid_consistency. @sql/share/errmsg-utf8.txt - Update error messages to be consistent with new logic.
1 parent a543141 commit ae750d6

20 files changed

+25201
-328
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# ==== Purpose ====
2+
#
3+
# Test many GTID-consistency violations. This file is sourced from
4+
# binlog_enforce_gtid_consistency.test; see that file for details.
5+
6+
--source extra/binlog_tests/enforce_gtid_consistency_create_select.test
7+
8+
--let $binlog_direct_non_transactional_updates= 0
9+
--source extra/binlog_tests/enforce_gtid_consistency_trx_nontrx.test
10+
11+
--let $binlog_direct_non_transactional_updates= 1
12+
--source extra/binlog_tests/enforce_gtid_consistency_trx_nontrx.test
13+
14+
--source extra/binlog_tests/enforce_gtid_consistency_temporary.test
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--echo ---- CREATE TABLE ... SELECT: violation cases ----
2+
3+
--let $error_code= ER_GTID_UNSAFE_CREATE_SELECT
4+
--let $error_message= Statement violates GTID consistency: CREATE TABLE ... SELECT.
5+
--let $gtid_violation= 1
6+
--let $expect_counter_value= 0
7+
8+
# CREATE...SELECT for base table is not allowed, regardless of engine,
9+
# since it may get logged as CREATE followed by BEGIN; rows; COMMIT
10+
# (on this server if binlog_format=row or on a slave that uses
11+
# binlog_format=row).
12+
13+
--echo # CREATE ... SELECT (InnoDB): Violation.
14+
--let $statement= CREATE TABLE t1 (a INT) ENGINE = InnoDB SELECT 1
15+
--source extra/binlog_tests/enforce_gtid_consistency_statement.inc
16+
DROP TABLE IF EXISTS t1;
17+
18+
--echo # CREATE ... SELECT (MyISAM): Violation.
19+
--let $statement= CREATE TABLE t1 (a INT) ENGINE = MyISAM SELECT 1
20+
--source extra/binlog_tests/enforce_gtid_consistency_statement.inc
21+
DROP TABLE IF EXISTS t1;
22+
23+
--echo ---- CREATE TABLE ... SELECT: consistent cases ----
24+
25+
# CREATE TEMPORARY...SELECT is GTID consistent since it cannot
26+
# generate row events, since temporary DML is never logged in row
27+
# format.
28+
29+
--echo # CREATE TEMPORARY ... SELECT: Consistent.
30+
--let $gtid_violation= 0
31+
32+
--let $statement= CREATE TEMPORARY TABLE t1 (a INT) ENGINE = InnoDB SELECT 1
33+
--source extra/binlog_tests/enforce_gtid_consistency_statement.inc
34+
DROP TABLE IF EXISTS t1;
35+
36+
--let $statement= CREATE TEMPORARY TABLE t1 (a INT) ENGINE = MyISAM SELECT 1
37+
--source extra/binlog_tests/enforce_gtid_consistency_statement.inc
38+
DROP TABLE IF EXISTS t1;
39+
40+
# When SQL_LOG_BIN=0, it is GTID-consistent since nothing is logged.
41+
42+
--echo # CREATE ... SELECT, SQL_LOG_BIN=0: Consistent.
43+
SET SQL_LOG_BIN = 0;
44+
--let $statement= CREATE TABLE t1 (a INT) ENGINE = InnoDB SELECT 1
45+
--source extra/binlog_tests/enforce_gtid_consistency_statement.inc
46+
DROP TABLE IF EXISTS t1;
47+
48+
--let $statement= CREATE TABLE t1 (a INT) ENGINE = MyISAM SELECT 1
49+
--source extra/binlog_tests/enforce_gtid_consistency_statement.inc
50+
DROP TABLE IF EXISTS t1;
51+
SET SQL_LOG_BIN = 1;
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# ==== Purpose ====
2+
#
3+
# This is an auxiliary test script used by
4+
# extra/binlog_tests/enforce_gtid_consistency.test. It tests that
5+
# GTID-consistency violation error/warning is generated correctly for
6+
# a statement.
7+
#
8+
# ==== Usage ====
9+
#
10+
# [--let $pre_statement= STATEMENT]
11+
# --let $gtid_next= VALUE
12+
# --let $statement= STATEMENT
13+
# --let $gtid_violation= [0|1]
14+
# --let $violation_result= [0|1|2]
15+
# --let $error= ER_SOMETHING
16+
# --let $error= some text
17+
#
18+
# Parameters:
19+
#
20+
# $pre_statement, $gtid_next, $statement
21+
# This script will do the following:
22+
# 1. Set GTID_NEXT='$gtid_next'. If $gtid_next is equal to GTID
23+
# (the four letters G, T, I, and D), then the script will
24+
# generate a GTID to use.
25+
# 2. Execute $pre_statement, if it is not empty.
26+
# 3. Execute $statement.
27+
#
28+
# $gtid_violation
29+
# Set this to 1 if it is expected that $statement generates a
30+
# GTID violation, 0 if not.
31+
#
32+
# $violation_result
33+
# Just because there is a GTID violation, it does not have to
34+
# result in an error. It could go through without problems
35+
# (e.g. if gtid_mode=off and enforce_gtid_consistency=off) or it
36+
# could generate a warning (e.g. if gtid_next!=UUID:NUMBER and
37+
# enforce_gtid_consistency=WARN) or it could generate an error
38+
# (e.g. if enforce_gtid_consistency=ON or gtid_next=UUID:NUMBER).
39+
# $violation_result specifies what is expected if this is a GTID
40+
# violation: 0 means no problem, 1 means error, and 2 means
41+
# warning.
42+
#
43+
# $expect_counter_value
44+
# If there is a violation but it does not result in an error
45+
# (i.e., $gtid_violation==1 and $violation_result!=1), then the
46+
# global counter ANONYMOUS_GTID_VIOLATING_TRANSACTION_COUNT or
47+
# AUTOMATIC_GTID_VIOLATING_TRANSACTION_COUNT should normally
48+
# increase by 1 for the duration of the transaction. Which of the
49+
# counters increases, depends on GTID_NEXT, and this script
50+
# automatically determines which variable it is using $gtid_next.
51+
# $expect_counter_value specifies the expected value of the
52+
# counter after $statement. Normally, if $statement ends the
53+
# transaction this value should be 0 since the commit decreases
54+
# the counter, whereas if $statement leaves the transaction open
55+
# this value should be
56+
#
57+
# $expect_counter_value_row
58+
# Normally, $expect_counter_value is used regardless of
59+
# BINLOG_FORMAT. But in some corner cases, the value of
60+
# $expect_counter_value depends on BINLOG_FORMAT. For those
61+
# cases, the caller should set $expect_counter_value to the
62+
# expected value when BINLOG_FORMAT==STATEMENT or MIXED, and
63+
# $expect_counter_value_row to the expected value when
64+
# BINLOG_FORMAT=ROW. The output to the result file will be
65+
# the same regardless of BINLOG_FORMAT.
66+
#
67+
# $error_code
68+
# The expected error code (ER_*), in case $statement generates an
69+
# error.
70+
#
71+
# $error_message
72+
# A substring of the error message text, in case $statement
73+
# generates an error.
74+
75+
--echo # enforce_gtid_consistency=$enforce_gtid_consistency gtid_mode=$gtid_mode gtid_next=$gtid_next
76+
77+
# $expectation is 0 if the statement is ok, 1 if an error is expected,
78+
# 2 if a warning is expected.
79+
--let $expectation= 0
80+
if ($gtid_violation)
81+
{
82+
--let $expectation= $violation_result
83+
}
84+
85+
if ($rpl_debug)
86+
{
87+
--echo gtid_violation='$gtid_violation' violation_result='$violation_result' error_code='$error_code' expectation='$expectation' expect_counter_value='$expect_counter_value' expect_counter_value_row='$expect_counter_value_row'
88+
--echo pre_statement='$pre_statement'
89+
--echo gtid_next='$gtid_next'
90+
--echo statement='$statement'
91+
}
92+
93+
--let $binlog_format= `SELECT @@GLOBAL.BINLOG_FORMAT`
94+
--source include/set_gtid_next_gtid_mode_agnostic.inc
95+
96+
if ($pre_statement != '')
97+
{
98+
eval $pre_statement;
99+
}
100+
101+
if ($expectation == 1)
102+
{
103+
--echo error $error_code
104+
--replace_regex /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}:[0-9]*/#/
105+
--error $error_code
106+
eval $statement;
107+
}
108+
if ($expectation != 1)
109+
{
110+
eval $statement;
111+
}
112+
113+
# Check warnings / errors.
114+
115+
--let $warning_count= `SHOW COUNT(*) WARNINGS`
116+
--let $warning_message= query_get_value(SHOW WARNINGS, Message, 1)
117+
--let $warning_level= query_get_value(SHOW WARNINGS, Level, 1)
118+
119+
--connection default
120+
121+
# The message may contain a single quote ('), which confuses
122+
# include/assert.inc So we remove any single quotes.
123+
--let $warning_message= `SELECT REPLACE("$warning_message", "'", "")`
124+
125+
if ($expectation == 0)
126+
{
127+
--let $assert_text= No warning or error should be generated.
128+
--let $assert_cond= $warning_count = 0
129+
--let $extra_debug_info= $warning_message
130+
--source include/assert.inc
131+
--let $extra_debug_info=
132+
}
133+
if ($expectation == 1)
134+
{
135+
--let $assert_text= One warning/error should be generated.
136+
--let $assert_cond= $warning_count = 1
137+
--source include/assert.inc
138+
139+
--let $assert_text= It should be an Error, not a Warning.
140+
--let $assert_cond= "$warning_level" = "Error"
141+
--source include/assert.inc
142+
143+
--let $assert_text= Text should be "violates GTID consistency"
144+
--let $assert_cond= "$warning_message" LIKE "$error_message%"
145+
--let $extra_debug_info= $warning_message
146+
--source include/assert.inc
147+
--let $extra_debug_info=
148+
}
149+
if ($expectation == 2)
150+
{
151+
--let $assert_text= One warning/error should be generated.
152+
--let $assert_cond= $warning_count = 1
153+
--source include/assert.inc
154+
155+
--let $assert_text= It should be a Warning, not an Error.
156+
--let $assert_cond= "$warning_level" = "Warning"
157+
--source include/assert.inc
158+
159+
--let $assert_text= Text should be "violates GTID consistency"
160+
--let $assert_cond= "$warning_message" LIKE "Statement violates GTID consistency%"
161+
--let $extra_debug_info= $warning_message
162+
--source include/assert.inc
163+
--let $extra_debug_info=
164+
}
165+
--connection server_1
166+
167+
# Check counters.
168+
--let $automatic_counter= query_get_value(SHOW STATUS LIKE "AUTOMATIC_GTID_VIOLATING_TRANSACTION_COUNT", Value, 1)
169+
--let $anonymous_counter= query_get_value(SHOW STATUS LIKE "ANONYMOUS_GTID_VIOLATING_TRANSACTION_COUNT", Value, 1)
170+
171+
--connection default
172+
173+
# Compute what counter values to expect. By default, expect both to be 0.
174+
--let $automatic_counter_expected= 0
175+
--let $anonymous_counter_expected= 0
176+
--let $automatic_counter_expected_text= 0
177+
--let $anonymous_counter_expected_text= 0
178+
if ($rpl_debug)
179+
{
180+
--echo !!!expectation='$expectation' cv='$expect_counter_value' gtid_next='$gtid_next'
181+
}
182+
if ($expectation != 1)
183+
{
184+
--let $expect_counter_text= $expect_counter_value
185+
if ($expect_counter_value_row != '')
186+
{
187+
--let $expect_counter_text= $expect_counter_value (stm) / $expect_counter_value_row (row)
188+
if ($binlog_format == 'ROW')
189+
{
190+
--let $expect_counter_value= $expect_counter_value_row
191+
}
192+
}
193+
if ($gtid_next == 'AUTOMATIC')
194+
{
195+
--let $automatic_counter_expected= $expect_counter_value
196+
--let $automatic_counter_expected_text= $expect_counter_text
197+
}
198+
if ($gtid_next == 'ANONYMOUS')
199+
{
200+
--let $anonymous_counter_expected= $expect_counter_value
201+
--let $anonymous_counter_expected_text= $expect_counter_text
202+
}
203+
}
204+
205+
--let $assert_text= AUTOMATIC_GTID_VIOLATING_TRANSACTION_COUNT should be $automatic_counter_expected_text
206+
--let $assert_cond= $automatic_counter = $automatic_counter_expected
207+
--source include/assert.inc
208+
209+
--let $assert_text= ANONYMOUS_GTID_VIOLATING_TRANSACTION_COUNT should be $anonymous_counter_expected_text
210+
--let $assert_cond= $anonymous_counter = $anonymous_counter_expected
211+
--source include/assert.inc
212+
213+
--connection server_1
214+
215+
# Clear transaction state.
216+
ROLLBACK;
217+
SET GTID_NEXT = 'AUTOMATIC';
218+
219+
# Check that counters are reset.
220+
--let $automatic_counter= query_get_value(SHOW STATUS LIKE "AUTOMATIC_GTID_VIOLATING_TRANSACTION_COUNT", Value, 1)
221+
--let $anonymous_counter= query_get_value(SHOW STATUS LIKE "ANONYMOUS_GTID_VIOLATING_TRANSACTION_COUNT", Value, 1)
222+
223+
--let $assert_text= Both counters should be 0
224+
--let $assert_cond= $automatic_counter = 0 AND $anonymous_counter = 0
225+
--source include/assert.inc
226+
227+
--let $expect_counter_value= 0
228+
--let $expect_counter_value_row=
229+
--let $pre_statement=
230+
--let $statements=

0 commit comments

Comments
 (0)