Skip to content

Commit 2f5670d

Browse files
committed
MDEV-11636 Extra persistent columns on slave always gets NULL in RBR
Problem:- In replication if slave has extra persistent column then these column are not computed while applying write-set from master. Solution:- While applying row events from server, we will generate values for extra persistent columns.
1 parent 8451e09 commit 2f5670d

File tree

4 files changed

+359
-0
lines changed

4 files changed

+359
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
include/master-slave.inc
2+
[connection master]
3+
connection master;
4+
create table t1(a int primary key);
5+
insert into t1 values(1);
6+
insert into t1 values(2);
7+
insert into t1 values(3);
8+
insert into t1 values(4);
9+
connection slave;
10+
select * from t1 order by a;
11+
a
12+
1
13+
2
14+
3
15+
4
16+
alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent;
17+
select * from t1 order by a;
18+
a z1 z2
19+
1 2 3
20+
2 3 4
21+
3 4 5
22+
4 5 6
23+
connection master;
24+
insert into t1 values(5);
25+
insert into t1 values(6);
26+
connection slave;
27+
select * from t1 order by a;
28+
a z1 z2
29+
1 2 3
30+
2 3 4
31+
3 4 5
32+
4 5 6
33+
5 6 7
34+
6 7 8
35+
#UPDATE query
36+
connection master;
37+
update t1 set a = a+10;
38+
select * from t1 order by a;
39+
a
40+
11
41+
12
42+
13
43+
14
44+
15
45+
16
46+
connection slave;
47+
select * from t1 order by a;
48+
a z1 z2
49+
11 12 13
50+
12 13 14
51+
13 14 15
52+
14 15 16
53+
15 16 17
54+
16 17 18
55+
connection master;
56+
update t1 set a = a-10;
57+
select * from t1 order by a;
58+
a
59+
1
60+
2
61+
3
62+
4
63+
5
64+
6
65+
connection slave;
66+
select * from t1 order by a;
67+
a z1 z2
68+
1 2 3
69+
2 3 4
70+
3 4 5
71+
4 5 6
72+
5 6 7
73+
6 7 8
74+
#DELETE quert
75+
connection master;
76+
delete from t1 where a > 2 and a < 4;
77+
select * from t1 order by a;
78+
a
79+
1
80+
2
81+
4
82+
5
83+
6
84+
connection slave;
85+
select * from t1 order by a;
86+
a z1 z2
87+
1 2 3
88+
2 3 4
89+
4 5 6
90+
5 6 7
91+
6 7 8
92+
#REPLACE query
93+
connection master;
94+
replace into t1 values(1);
95+
replace into t1 values(3);
96+
replace into t1 values(1);
97+
connection slave;
98+
select * from t1 order by a;
99+
a z1 z2
100+
1 2 3
101+
2 3 4
102+
3 4 5
103+
4 5 6
104+
5 6 7
105+
6 7 8
106+
#SELECT query
107+
connection master;
108+
select * from t1 where a > 2 and a < 4;
109+
a
110+
3
111+
connection slave;
112+
select * from t1 where a > 2 and a < 4;
113+
a z1 z2
114+
3 4 5
115+
#UPDATE with SELECT query
116+
connection master;
117+
update t1 set a = a + 10 where a > 2 and a < 4;
118+
select * from t1 order by a;
119+
a
120+
1
121+
2
122+
4
123+
5
124+
6
125+
13
126+
connection slave;
127+
select * from t1 order by a;
128+
a z1 z2
129+
1 2 3
130+
2 3 4
131+
4 5 6
132+
5 6 7
133+
6 7 8
134+
13 14 15
135+
connection master;
136+
update t1 set a = a - 10 where a = 13;
137+
select * from t1 order by a;
138+
a
139+
1
140+
2
141+
3
142+
4
143+
5
144+
6
145+
connection slave;
146+
select * from t1 order by a;
147+
a z1 z2
148+
1 2 3
149+
2 3 4
150+
3 4 5
151+
4 5 6
152+
5 6 7
153+
6 7 8
154+
#Break Unique Constraint
155+
alter table t1 add column z4 int as (a % 6) persistent unique;
156+
connection master;
157+
#entering duplicate value for slave persistent column
158+
insert into t1 values(7);
159+
select * from t1 order by a;
160+
a
161+
1
162+
2
163+
3
164+
4
165+
5
166+
6
167+
7
168+
connection slave;
169+
include/wait_for_slave_sql_error.inc [errno=1062]
170+
connection slave;
171+
connection slave;
172+
select * from t1 order by a;
173+
a z1 z2 z4
174+
1 2 3 1
175+
2 3 4 2
176+
3 4 5 3
177+
4 5 6 4
178+
5 6 7 5
179+
6 7 8 0
180+
alter table t1 drop column z4;
181+
start slave;
182+
include/wait_for_slave_sql_to_start.inc
183+
connection slave;
184+
connection slave;
185+
connection master;
186+
connection slave;
187+
select * from t1 order by a;
188+
a z1 z2
189+
1 2 3
190+
2 3 4
191+
3 4 5
192+
4 5 6
193+
5 6 7
194+
6 7 8
195+
7 8 9
196+
connection master;
197+
select * from t1 order by a;
198+
a
199+
1
200+
2
201+
3
202+
4
203+
5
204+
6
205+
7
206+
drop table t1;
207+
include/rpl_end.inc
208+
connection server_2;
209+
connection server_2;
210+
connection server_2;
211+
connection server_2;
212+
connection server_1;
213+
connection server_1;
214+
connection server_1;
215+
connection server_2;
216+
connection server_1;
217+
connection server_2;
218+
connection server_2;
219+
connection server_1;
220+
connection server_1;
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
--source include/master-slave.inc
2+
--source include/have_binlog_format_row.inc
3+
4+
--enable_connect_log
5+
--connection master
6+
create table t1(a int primary key);
7+
insert into t1 values(1);
8+
insert into t1 values(2);
9+
insert into t1 values(3);
10+
insert into t1 values(4);
11+
12+
--sync_slave_with_master
13+
select * from t1 order by a;
14+
alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent;
15+
select * from t1 order by a;
16+
17+
--connection master
18+
insert into t1 values(5);
19+
insert into t1 values(6);
20+
21+
--sync_slave_with_master
22+
select * from t1 order by a;
23+
24+
25+
--echo #UPDATE query
26+
27+
--connection master
28+
update t1 set a = a+10;
29+
select * from t1 order by a;
30+
31+
--sync_slave_with_master
32+
select * from t1 order by a;
33+
34+
--connection master
35+
update t1 set a = a-10;
36+
select * from t1 order by a;
37+
38+
--sync_slave_with_master
39+
select * from t1 order by a;
40+
41+
--echo #DELETE quert
42+
--connection master
43+
delete from t1 where a > 2 and a < 4;
44+
select * from t1 order by a;
45+
46+
--sync_slave_with_master
47+
select * from t1 order by a;
48+
49+
--echo #REPLACE query
50+
--connection master
51+
replace into t1 values(1);
52+
replace into t1 values(3);
53+
replace into t1 values(1);
54+
55+
--sync_slave_with_master
56+
select * from t1 order by a;
57+
58+
--echo #SELECT query
59+
--connection master
60+
select * from t1 where a > 2 and a < 4;
61+
62+
--connection slave
63+
select * from t1 where a > 2 and a < 4;
64+
65+
--echo #UPDATE with SELECT query
66+
--connection master
67+
update t1 set a = a + 10 where a > 2 and a < 4;
68+
select * from t1 order by a;
69+
70+
--sync_slave_with_master
71+
select * from t1 order by a;
72+
73+
--connection master
74+
update t1 set a = a - 10 where a = 13;
75+
select * from t1 order by a;
76+
77+
--sync_slave_with_master
78+
select * from t1 order by a;
79+
80+
--echo #Break Unique Constraint
81+
alter table t1 add column z4 int as (a % 6) persistent unique;
82+
83+
--connection master
84+
85+
--echo #entering duplicate value for slave persistent column
86+
insert into t1 values(7);
87+
select * from t1 order by a;
88+
89+
--connection slave
90+
--let $slave_sql_errno= 1062
91+
--source include/wait_for_slave_sql_error.inc
92+
select * from t1 order by a;
93+
alter table t1 drop column z4;
94+
start slave;
95+
96+
--source include/wait_for_slave_sql_to_start.inc
97+
98+
--connection master
99+
--sync_slave_with_master
100+
select * from t1 order by a;
101+
102+
--connection master
103+
select * from t1 order by a;
104+
drop table t1;
105+
106+
--source include/rpl_end.inc

sql/rpl_record.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,13 @@ unpack_row(rpl_group_info *rgi,
416416
}
417417
}
418418

419+
/*
420+
Add Extra slave persistent columns
421+
*/
422+
int error= 0;
423+
if ((error= fill_extra_persistent_columns(table, cols->n_bits)))
424+
DBUG_RETURN(error);
425+
419426
/*
420427
We should now have read all the null bytes, otherwise something is
421428
really wrong.
@@ -489,5 +496,30 @@ int prepare_record(TABLE *const table, const uint skip, const bool check)
489496

490497
DBUG_RETURN(0);
491498
}
499+
/**
500+
Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master.
501+
@param table Table whose record[0] buffer is prepared.
502+
@param master_cols No of columns on master
503+
@returns 0 on success
504+
*/
505+
int fill_extra_persistent_columns(TABLE *table, int master_cols)
506+
{
507+
int error= 0;
508+
Field **vfield_ptr, *vfield;
492509

510+
if (!table->vfield)
511+
return 0;
512+
for (vfield_ptr= table->vfield; *vfield_ptr; ++vfield_ptr)
513+
{
514+
vfield= *vfield_ptr;
515+
if (vfield->field_index >= master_cols && vfield->stored_in_db)
516+
{
517+
/*Set bitmap for writing*/
518+
bitmap_set_bit(table->vcol_set, vfield->field_index);
519+
error= vfield->vcol_info->expr_item->save_in_field(vfield,0);
520+
bitmap_clear_bit(table->vcol_set, vfield->field_index);
521+
}
522+
}
523+
return error;
524+
}
493525
#endif // HAVE_REPLICATION

sql/rpl_record.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ int unpack_row(rpl_group_info *rgi,
3838

3939
// Fill table's record[0] with default values.
4040
int prepare_record(TABLE *const table, const uint skip, const bool check);
41+
int fill_extra_persistent_columns(TABLE *table, int master_cols);
4142
#endif
4243

4344
#endif

0 commit comments

Comments
 (0)