Skip to content

Commit bd17d9d

Browse files
author
Hemant Dangi
committed
BUG#26985561: BACKPORT BUG#26277771 TO 5.7
This is backport of Bug#26277771: BAD WRITE SET TRACKING WITH UNIQUE KEY ON A DELETE FOLLOWED BY AN INSERT. Issue: ====== The Writesets generated for keys were not using collation into consideration, and because of that wrong last_committed and sequence_number were getting added to binary log and thus trnsactions were getting applied in wrong order by parallel applier on slave. Solution: ========= The fix uses make_sort_key to transform keys, with different charset and collation, into its binary image, suitable for sorting using binary comparison.
1 parent e0ad9ea commit bd17d9d

10 files changed

+689
-149
lines changed

mysql-test/suite/rpl/r/rpl_transaction_write_set_extraction.result

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Note #### Storing MySQL user name or password information in the master info rep
55
[connection master]
66
include/assert.inc [The value for transaction_write_set_extraction shoudl be MURMUR32]
77
CREATE TABLE t1 (a INT PRIMARY KEY);
8-
SET @@GLOBAL.DEBUG= @debug_saved;
8+
SET @debug_saved= @@GLOBAL.DEBUG;
99
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_key_generated_insert';
1010
INSERT INTO t1 VALUES(1);
1111
SET @@GLOBAL.DEBUG= @debug_saved;
@@ -15,6 +15,17 @@ SET @@GLOBAL.DEBUG= @debug_saved;
1515
include/rpl_sync.inc
1616
DROP TABLE t1;
1717
include/rpl_sync.inc
18+
CREATE TABLE t1 (a BINARY(1) PRIMARY KEY);
19+
SET @@GLOBAL.DEBUG= @debug_saved;
20+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_key_generated_insert_collation';
21+
INSERT INTO t1 VALUES(1);
22+
SET @@GLOBAL.DEBUG= @debug_saved;
23+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_key_generated_update_collation';
24+
UPDATE t1 SET a=3 WHERE a=1;
25+
SET @@GLOBAL.DEBUG= @debug_saved;
26+
include/rpl_sync.inc
27+
DROP TABLE t1;
28+
include/rpl_sync.inc
1829
CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));
1930
SET @@GLOBAL.DEBUG= @debug_saved;
2031
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_key_generated_insert';
@@ -26,6 +37,17 @@ SET @@GLOBAL.DEBUG= @debug_saved;
2637
include/rpl_sync.inc
2738
DROP TABLE t1;
2839
include/rpl_sync.inc
40+
CREATE TABLE t1(a BINARY(1), b BINARY(1), PRIMARY KEY(a, b));
41+
SET @@GLOBAL.DEBUG= @debug_saved;
42+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_key_generated_insert_collation';
43+
INSERT INTO t1 VALUE(1, 2);
44+
SET @@GLOBAL.DEBUG= @debug_saved;
45+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_key_generated_update_collation';
46+
UPDATE t1 SET a=3 WHERE a=1;
47+
SET @@GLOBAL.DEBUG= @debug_saved;
48+
include/rpl_sync.inc
49+
DROP TABLE t1;
50+
include/rpl_sync.inc
2951
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT NOT NULL UNIQUE, c3 INT NOT NULL UNIQUE);
3052
SET @@GLOBAL.DEBUG= @debug_saved;
3153
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_unique_key_generated_insert';
@@ -36,6 +58,16 @@ UPDATE t1 SET c1=5 WHERE c1=1;
3658
include/rpl_sync.inc
3759
DROP TABLE t1;
3860
include/rpl_sync.inc
61+
CREATE TABLE t1 (c1 BINARY(1) PRIMARY KEY, c2 BINARY(1) NOT NULL UNIQUE, c3 BINARY(1) NOT NULL UNIQUE);
62+
SET @@GLOBAL.DEBUG= @debug_saved;
63+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_unique_key_generated_insert_collation';
64+
INSERT INTO t1 VALUES (1, 2, 3);
65+
SET @@GLOBAL.DEBUG= @debug_saved;
66+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_unique_key_generated_update_collation';
67+
UPDATE t1 SET c1=5 WHERE c1=1;
68+
include/rpl_sync.inc
69+
DROP TABLE t1;
70+
include/rpl_sync.inc
3971
CREATE TABLE t1 (a INT, d INT, b INT NOT NULL UNIQUE, c INT NOT NULL UNIQUE, PRIMARY KEY(a, d));
4072
SET @@GLOBAL.DEBUG= @debug_saved;
4173
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_unique_key_generated_insert';
@@ -47,6 +79,17 @@ SET @@GLOBAL.DEBUG= @debug_saved;
4779
include/rpl_sync.inc
4880
DROP TABLE t1;
4981
include/rpl_sync.inc
82+
CREATE TABLE t1 (a BINARY(1), d BINARY(1), b BINARY(1) NOT NULL UNIQUE, c BINARY(1) NOT NULL UNIQUE, PRIMARY KEY(a, d));
83+
SET @@GLOBAL.DEBUG= @debug_saved;
84+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_unique_key_generated_insert_collation';
85+
INSERT INTO t1 VALUES(1, 2, 3, 4);
86+
SET @@GLOBAL.DEBUG= @debug_saved;
87+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_unique_key_generated_update_collation';
88+
UPDATE t1 SET a=5 WHERE a=1;
89+
SET @@GLOBAL.DEBUG= @debug_saved;
90+
include/rpl_sync.inc
91+
DROP TABLE t1;
92+
include/rpl_sync.inc
5093
CREATE TABLE t1 (a INT PRIMARY KEY);
5194
CREATE TABLE t2 (b INT PRIMARY KEY);
5295
CREATE TABLE t3 (c1 INT, c2 INT NOT NULL UNIQUE, PRIMARY KEY(c1, c2), FOREIGN KEY(c1) REFERENCES t1(a), FOREIGN KEY(c2) REFERENCES t2(b));
@@ -66,4 +109,23 @@ DROP TABLE t3;
66109
DROP TABLE t2;
67110
DROP TABLE t1;
68111
include/rpl_sync.inc
112+
CREATE TABLE t1 (a BINARY(1) PRIMARY KEY);
113+
CREATE TABLE t2 (b BINARY(1) PRIMARY KEY);
114+
CREATE TABLE t3 (c1 BINARY(1), c2 BINARY(1) NOT NULL UNIQUE, PRIMARY KEY(c1, c2), FOREIGN KEY(c1) REFERENCES t1(a), FOREIGN KEY(c2) REFERENCES t2(b));
115+
INSERT INTO t1 VALUES (1);
116+
INSERT INTO t2 VALUES (5);
117+
SET @@GLOBAL.DEBUG= @debug_saved;
118+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_foreign_key_generated_insert_collation';
119+
INSERT INTO t3 values(1,5);
120+
SET @@GLOBAL.DEBUG= @debug_saved;
121+
INSERT INTO t1 VALUES (3);
122+
include/rpl_sync.inc
123+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_foreign_key_generated_update_collation';
124+
UPDATE t3 SET c1=3 WHERE c1=1;
125+
include/rpl_sync.inc
126+
SET @@GLOBAL.DEBUG= @debug_saved;
127+
DROP TABLE t3;
128+
DROP TABLE t2;
129+
DROP TABLE t1;
130+
include/rpl_sync.inc
69131
include/rpl_end.inc

mysql-test/suite/rpl/t/rpl_transaction_write_set_extraction.test

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
--connection master
1919
CREATE TABLE t1 (a INT PRIMARY KEY);
20-
SET @@GLOBAL.DEBUG= @debug_saved;
20+
SET @debug_saved= @@GLOBAL.DEBUG;
2121
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_key_generated_insert';
2222
INSERT INTO t1 VALUES(1);
2323
SET @@GLOBAL.DEBUG= @debug_saved;
@@ -28,8 +28,23 @@ SET @@GLOBAL.DEBUG= @debug_saved;
2828
DROP TABLE t1;
2929
--source include/rpl_sync.inc
3030

31+
# tests both writeset algorithm (with and without collation)
32+
--connection master
33+
CREATE TABLE t1 (a BINARY(1) PRIMARY KEY);
34+
SET @@GLOBAL.DEBUG= @debug_saved;
35+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_key_generated_insert_collation';
36+
INSERT INTO t1 VALUES(1);
37+
SET @@GLOBAL.DEBUG= @debug_saved;
38+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_key_generated_update_collation';
39+
UPDATE t1 SET a=3 WHERE a=1;
40+
SET @@GLOBAL.DEBUG= @debug_saved;
41+
--source include/rpl_sync.inc
42+
DROP TABLE t1;
43+
--source include/rpl_sync.inc
44+
3145
# Table with multi values pimary key field with insert and update
3246

47+
--connection master
3348
CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));
3449
SET @@GLOBAL.DEBUG= @debug_saved;
3550
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_key_generated_insert';
@@ -42,6 +57,20 @@ SET @@GLOBAL.DEBUG= @debug_saved;
4257
DROP TABLE t1;
4358
--source include/rpl_sync.inc
4459

60+
# tests both writeset algorithm (with and without collation)
61+
--connection master
62+
CREATE TABLE t1(a BINARY(1), b BINARY(1), PRIMARY KEY(a, b));
63+
SET @@GLOBAL.DEBUG= @debug_saved;
64+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_key_generated_insert_collation';
65+
INSERT INTO t1 VALUE(1, 2);
66+
SET @@GLOBAL.DEBUG= @debug_saved;
67+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_key_generated_update_collation';
68+
UPDATE t1 SET a=3 WHERE a=1;
69+
SET @@GLOBAL.DEBUG= @debug_saved;
70+
--source include/rpl_sync.inc
71+
DROP TABLE t1;
72+
--source include/rpl_sync.inc
73+
4574
# Table with single primary key and multiple unique key with insert and
4675
# updates.
4776

@@ -57,9 +86,23 @@ UPDATE t1 SET c1=5 WHERE c1=1;
5786
DROP TABLE t1;
5887
--source include/rpl_sync.inc
5988

89+
# tests both writeset algorithm (with and without collation)
90+
--connection master
91+
CREATE TABLE t1 (c1 BINARY(1) PRIMARY KEY, c2 BINARY(1) NOT NULL UNIQUE, c3 BINARY(1) NOT NULL UNIQUE);
92+
SET @@GLOBAL.DEBUG= @debug_saved;
93+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_unique_key_generated_insert_collation';
94+
INSERT INTO t1 VALUES (1, 2, 3);
95+
SET @@GLOBAL.DEBUG= @debug_saved;
96+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_single_primary_unique_key_generated_update_collation';
97+
UPDATE t1 SET c1=5 WHERE c1=1;
98+
--source include/rpl_sync.inc
99+
DROP TABLE t1;
100+
--source include/rpl_sync.inc
101+
60102
# Table with multi valued primary key and multiple unique key with insert and
61103
# updates.
62104

105+
--connection master
63106
CREATE TABLE t1 (a INT, d INT, b INT NOT NULL UNIQUE, c INT NOT NULL UNIQUE, PRIMARY KEY(a, d));
64107
SET @@GLOBAL.DEBUG= @debug_saved;
65108
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_unique_key_generated_insert';
@@ -72,6 +115,20 @@ SET @@GLOBAL.DEBUG= @debug_saved;
72115
DROP TABLE t1;
73116
--source include/rpl_sync.inc
74117

118+
# tests both writeset algorithm (with and without collation)
119+
--connection master
120+
CREATE TABLE t1 (a BINARY(1), d BINARY(1), b BINARY(1) NOT NULL UNIQUE, c BINARY(1) NOT NULL UNIQUE, PRIMARY KEY(a, d));
121+
SET @@GLOBAL.DEBUG= @debug_saved;
122+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_unique_key_generated_insert_collation';
123+
INSERT INTO t1 VALUES(1, 2, 3, 4);
124+
SET @@GLOBAL.DEBUG= @debug_saved;
125+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_primary_unique_key_generated_update_collation';
126+
UPDATE t1 SET a=5 WHERE a=1;
127+
SET @@GLOBAL.DEBUG= @debug_saved;
128+
--source include/rpl_sync.inc
129+
DROP TABLE t1;
130+
--source include/rpl_sync.inc
131+
75132
# Table with Primary Key + Unique Key and Foreign Key
76133

77134
--connection master
@@ -97,4 +154,27 @@ DROP TABLE t2;
97154
DROP TABLE t1;
98155
--source include/rpl_sync.inc
99156

157+
# tests both writeset algorithm (with and without collation)
158+
--connection master
159+
CREATE TABLE t1 (a BINARY(1) PRIMARY KEY);
160+
CREATE TABLE t2 (b BINARY(1) PRIMARY KEY);
161+
CREATE TABLE t3 (c1 BINARY(1), c2 BINARY(1) NOT NULL UNIQUE, PRIMARY KEY(c1, c2), FOREIGN KEY(c1) REFERENCES t1(a), FOREIGN KEY(c2) REFERENCES t2(b));
162+
163+
INSERT INTO t1 VALUES (1);
164+
INSERT INTO t2 VALUES (5);
165+
SET @@GLOBAL.DEBUG= @debug_saved;
166+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_foreign_key_generated_insert_collation';
167+
INSERT INTO t3 values(1,5);
168+
SET @@GLOBAL.DEBUG= @debug_saved;
169+
INSERT INTO t1 VALUES (3);
170+
--source include/rpl_sync.inc
171+
SET @@GLOBAL.DEBUG= '+d,PKE_assert_multi_foreign_key_generated_update_collation';
172+
UPDATE t3 SET c1=3 WHERE c1=1;
173+
--source include/rpl_sync.inc
174+
SET @@GLOBAL.DEBUG= @debug_saved;
175+
DROP TABLE t3;
176+
DROP TABLE t2;
177+
DROP TABLE t1;
178+
--source include/rpl_sync.inc
179+
100180
--source include/rpl_end.inc

rapid/plugin/group_replication/tests/mtr/r/gr_certifier_garbage_collection.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ UPDATE t1 SET c1=2 WHERE c1=1;
3838
# After garbage collection certification info will contain:
3939
# WS: t1.c1=1 -> 8a94f357-aab4-11df-86ab-c80aa9422222:1-4
4040
# WS: t1.c1=2 -> 8a94f357-aab4-11df-86ab-c80aa9422222:1-4
41-
include/assert.inc ['Count_transactions_rows_validating must be 2']
41+
include/assert.inc ['Count_transactions_rows_validating must be 4']
4242
include/assert.inc ['Transactions_committed_all_members must be equal to 8a94f357-aab4-11df-86ab-c80aa9422222:1-4']
43-
include/assert.inc ['Count_transactions_rows_validating must be 2']
43+
include/assert.inc ['Count_transactions_rows_validating must be 4']
4444
include/assert.inc ['Transactions_committed_all_members must be equal to 8a94f357-aab4-11df-86ab-c80aa9422222:1-4']
4545

4646
############################################################
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
include/group_replication.inc
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5+
[connection server1]
6+
7+
###########################
8+
# Create a table on server1
9+
[connection server1]
10+
CREATE TABLE t1 (
11+
u_str VARCHAR(32) NOT NULL,
12+
value VARCHAR(32) NOT NULL,
13+
PRIMARY KEY (u_str)
14+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
15+
include/rpl_sync.inc
16+
17+
######################################################################
18+
# Execute in concurrency transaction with equivalent keys under latin1
19+
20+
############################################################
21+
# 0. Initial setup and checks.
22+
[connection server_1]
23+
SET SESSION sql_log_bin= 0;
24+
include/gtid_utils.inc
25+
SET SESSION sql_log_bin= 1;
26+
include/gtid_step_reset.inc
27+
28+
############################################################
29+
# 1. Set a debug sync before broadcast message to group on
30+
# connection local_server_connection1.
31+
[connection server_1]
32+
SET @debug_save= @@GLOBAL.DEBUG;
33+
SET @@GLOBAL.DEBUG='d,group_replication_before_message_broadcast';
34+
35+
#####################################################################
36+
# 2. Commit local_transaction that will be blocked before broadcast.
37+
BEGIN;
38+
INSERT INTO t1 (u_str, value) VALUES ('�', "A value");;
39+
COMMIT;
40+
41+
############################################################
42+
# 3. Wait until local transaction reaches the
43+
# group_replication_before_message_broadcast debug sync point.
44+
[connection server1]
45+
46+
############################################################
47+
# 4. Execute a transaction on remote server, that will reach first
48+
# certification, since transaction on the local server
49+
# is blocked before broadcast.
50+
[connection server2]
51+
BEGIN;
52+
INSERT INTO t1 (u_str, value) VALUES ('�', "Another value");;
53+
COMMIT;
54+
55+
############################################################
56+
# 5. Signal the waiting thread on local server to resume the
57+
# transaction.
58+
[connection server1]
59+
SET DEBUG_SYNC='now SIGNAL waiting';
60+
SET @@GLOBAL.DEBUG= @debug_save;
61+
62+
############################################################
63+
# 6. Wait for remote transaction to be executed succesfully
64+
on local server.
65+
[connection server2]
66+
include/sync_slave_sql_with_master.inc
67+
############################################################
68+
# 7. If the test case is conflict scenario, local transaction
69+
# will end up in an error stating that it was aborted,
70+
# since transactions are conflicting and transaction on
71+
# remote server was ordered first. If the test case is
72+
# is positive scenario, no error will be seen here.
73+
[connection server_1]
74+
ERROR HY000: Plugin instructed the server to rollback the current transaction.
75+
[connection server_1]
76+
SET @@GLOBAL.DEBUG=@debug_save;
77+
############################################################
78+
# 8. Sync everything
79+
include/rpl_sync.inc
80+
############################################################
81+
# 9. Assert that number of certified transactions are the
82+
# expected ones.
83+
include/assert.inc [The value of Count_Transactions_Checked should be 3 after starting group replication]
84+
include/assert.inc [The value of Count_Conflicts_Detected should be 1 after starting group replication]
85+
############################################################
86+
# 10. Assert that GTID is increased as expected
87+
include/gtid_step_assert.inc [count=1, only_count=1]
88+
[connection server_1]
89+
SET SESSION sql_log_bin= 0;
90+
include/gtid_utils_end.inc
91+
SET SESSION sql_log_bin= 1;
92+
############################################################
93+
# 11. Cleanup (restore the connection back to original)
94+
[connection server1]
95+
96+
###########
97+
# Clean up.
98+
DROP TABLE t1;
99+
include/group_replication_end.inc

rapid/plugin/group_replication/tests/mtr/r/gr_perfschema_group_member_stats.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ server1
5353
include/assert.inc [The value of member_id should be equal to server UUID after starting group replication]
5454
include/assert.inc [The value of Count_Transactions_checked should be 6 after starting group replication]
5555
include/assert.inc [The value of Count_conflicts_detected should be 0 after starting group replication]
56-
include/assert.inc [The value of Count_Transactions_rows_validating should be 2 after starting group replication]
56+
include/assert.inc [The value of Count_Transactions_rows_validating should be 4 after starting group replication]
5757
include/assert.inc [The value of Transactions_committed_all_members should have server 1 GTIDs before server2 start]
5858
include/assert.inc [The value of Last_Conflict_free_transaction should be the gtid of the last applied transaction.]
5959
SET SESSION sql_log_bin= 0;

rapid/plugin/group_replication/tests/mtr/t/gr_certifier_garbage_collection.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ UPDATE t1 SET c1=2 WHERE c1=1;
104104

105105
--connection server1
106106
--let $count_transactions_validating= query_get_value(SELECT Count_transactions_rows_validating from performance_schema.replication_group_member_stats, Count_transactions_rows_validating, 1)
107-
--let $assert_text= 'Count_transactions_rows_validating must be 2'
108-
--let $assert_cond= $count_transactions_validating = 2
107+
--let $assert_text= 'Count_transactions_rows_validating must be 4'
108+
--let $assert_cond= $count_transactions_validating = 4
109109
--source include/assert.inc
110110

111111
--let $transactions_committed_all_members= query_get_value(SELECT Transactions_committed_all_members from performance_schema.replication_group_member_stats, Transactions_committed_all_members, 1)
@@ -115,8 +115,8 @@ UPDATE t1 SET c1=2 WHERE c1=1;
115115

116116
--connection server2
117117
--let $count_transactions_validating= query_get_value(SELECT Count_transactions_rows_validating from performance_schema.replication_group_member_stats, Count_transactions_rows_validating, 1)
118-
--let $assert_text= 'Count_transactions_rows_validating must be 2'
119-
--let $assert_cond= $count_transactions_validating = 2
118+
--let $assert_text= 'Count_transactions_rows_validating must be 4'
119+
--let $assert_cond= $count_transactions_validating = 4
120120
--source include/assert.inc
121121

122122
--let $transactions_committed_all_members= query_get_value(SELECT Transactions_committed_all_members from performance_schema.replication_group_member_stats, Transactions_committed_all_members, 1)

0 commit comments

Comments
 (0)