Merge lp:~laurynas-biveinis/percona-server/fake-changes-binlog-5.5 into lp:percona-server/5.5

Proposed by Laurynas Biveinis
Status: Superseded
Proposed branch: lp:~laurynas-biveinis/percona-server/fake-changes-binlog-5.5
Merge into: lp:percona-server/5.5
Diff against target: 309 lines (+238/-2)
5 files modified
Percona-Server/mysql-test/suite/binlog/r/binlog_percona_fake_changes.result (+72/-0)
Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test (+106/-0)
Percona-Server/sql/handler.cc (+20/-1)
Percona-Server/sql/handler.h (+1/-0)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+39/-1)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-server/fake-changes-binlog-5.5
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Needs Fixing
Vlad Lesin (community) g2 Approve
Review via email: mp+170781@code.launchpad.net

This proposal has been superseded by a proposal from 2013-08-23.

Description of the change

No BT or ST, but prerequisite for BT 20439, as well as being quite critical bug for the fake changes feature.

Manually merge bug 1190580 and bug 1188162 fixes from 5.1.

http://jenkins.percona.com/job/percona-server-5.5-param/770/

To post a comment you must log in.
Revision history for this message
Vlad Lesin (vlad-lesin) :
review: Approve (g2)
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Same comments as in 5.1.

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'Percona-Server/mysql-test/suite/binlog/r/binlog_percona_fake_changes.result'
2--- Percona-Server/mysql-test/suite/binlog/r/binlog_percona_fake_changes.result 1970-01-01 00:00:00 +0000
3+++ Percona-Server/mysql-test/suite/binlog/r/binlog_percona_fake_changes.result 2013-08-22 13:22:00 +0000
4@@ -0,0 +1,72 @@
5+DROP TABLE IF EXISTS t1;
6+DROP TABLE IF EXISTS t2;
7+DROP TABLE IF EXISTS t3;
8+CREATE TABLE t1 (a INT PRIMARY KEY, b int) ENGINE=InnoDB;
9+INSERT INTO t1 VALUES (1,1);
10+CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE=InnoDB;
11+CREATE INDEX bx ON t2(b);
12+INSERT INTO t2 VALUES (1,1);
13+CREATE TABLE t3 (a INT PRIMARY KEY, b text) ENGINE=InnoDB;
14+INSERT INTO t3 VALUES (1,'');
15+RESET MASTER;
16+SET innodb_fake_changes=1;
17+SELECT * FROM t1;
18+ERROR HY000: Got error 131 during COMMIT
19+SELECT * FROM t2;
20+ERROR HY000: Got error 131 during COMMIT
21+SELECT * FROM t3;
22+ERROR HY000: Got error 131 during COMMIT
23+INSERT INTO t1 VALUES (2,2);
24+ERROR HY000: Got error 131 during COMMIT
25+INSERT INTO t2 VALUES (2,2);
26+ERROR HY000: Got error 131 during COMMIT
27+INSERT INTO t3 VALUES (2,lpad('a',10000, 'b'));
28+ERROR HY000: Got error 131 during COMMIT
29+UPDATE t1 SET a=0 where b=1;
30+ERROR HY000: Got error 131 during COMMIT
31+UPDATE t2 SET a=0 where b=1;
32+ERROR HY000: Got error 131 during COMMIT
33+UPDATE t3 SET a=0 where a=1;
34+ERROR HY000: Got error 131 during COMMIT
35+UPDATE t1 SET b=0 where a=1;
36+ERROR HY000: Got error 131 during COMMIT
37+UPDATE t2 SET b=0 where a=1;
38+ERROR HY000: Got error 131 during COMMIT
39+UPDATE t2 SET b=lpad('a',10000, 'z') where a=1;
40+ERROR HY000: Got error 131 during COMMIT
41+UPDATE t1 SET b=0 where a=2;
42+ERROR HY000: Got error 131 during COMMIT
43+UPDATE t2 SET b=0 where a=2;
44+ERROR HY000: Got error 131 during COMMIT
45+UPDATE t2 SET b=lpad('a',10000, 'z') where a=2;
46+ERROR HY000: Got error 131 during COMMIT
47+DELETE FROM t1 where b=2;
48+ERROR HY000: Got error 131 during COMMIT
49+DELETE FROM t2 where b=2;
50+ERROR HY000: Got error 131 during COMMIT
51+DELETE FROM t1 where a=2;
52+ERROR HY000: Got error 131 during COMMIT
53+DELETE FROM t2 where a=2;
54+ERROR HY000: Got error 131 during COMMIT
55+DELETE FROM t3 where a=2;
56+ERROR HY000: Got error 131 during COMMIT
57+REPLACE INTO t1 values (2,3);
58+ERROR HY000: Got error 131 during COMMIT
59+REPLACE INTO t2 values (2,3);
60+ERROR HY000: Got error 131 during COMMIT
61+REPLACE INTO t3 values (2,lpad('a',9000,'q'));
62+ERROR HY000: Got error 131 during COMMIT
63+INSERT INTO t1 VALUES (1,1) ON DUPLICATE KEY UPDATE b=2;
64+ERROR HY000: Got error 131 during COMMIT
65+INSERT INTO t2 VALUES (1,1) ON DUPLICATE KEY UPDATE b=2;
66+ERROR HY000: Got error 131 during COMMIT
67+INSERT INTO t3 VALUES (1,1) ON DUPLICATE KEY UPDATE b=lpad('b',11000,'c');
68+ERROR HY000: Got error 131 during COMMIT
69+show binlog events from <binlog_start>;
70+Log_name Pos Event_type Server_id End_log_pos Info
71+must_be_1
72+1
73+SET innodb_fake_changes=default;
74+DROP TABLE t1;
75+DROP TABLE t2;
76+DROP TABLE t3;
77
78=== added file 'Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test'
79--- Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test 1970-01-01 00:00:00 +0000
80+++ Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test 2013-08-22 13:22:00 +0000
81@@ -0,0 +1,106 @@
82+#
83+# Test that fake changes are not written to binlog
84+# Based on rpl_percona_fake_changes.test in Facebook patch
85+# https://bugs.launchpad.net/percona-server/+bug/1190580
86+# https://bugs.launchpad.net/percona-server/+bug/1188162
87+#
88+
89+--source include/have_log_bin.inc
90+--source include/have_innodb.inc
91+
92+--disable_warnings
93+DROP TABLE IF EXISTS t1;
94+DROP TABLE IF EXISTS t2;
95+DROP TABLE IF EXISTS t3;
96+--enable_warnings
97+
98+CREATE TABLE t1 (a INT PRIMARY KEY, b int) ENGINE=InnoDB;
99+INSERT INTO t1 VALUES (1,1);
100+
101+CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE=InnoDB;
102+CREATE INDEX bx ON t2(b);
103+INSERT INTO t2 VALUES (1,1);
104+
105+CREATE TABLE t3 (a INT PRIMARY KEY, b text) ENGINE=InnoDB;
106+INSERT INTO t3 VALUES (1,'');
107+
108+RESET MASTER;
109+
110+let $binlog_pos_1= query_get_value("SHOW MASTER STATUS", Position, 1);
111+
112+SET innodb_fake_changes=1;
113+
114+--error ER_ERROR_DURING_COMMIT
115+SELECT * FROM t1;
116+--error ER_ERROR_DURING_COMMIT
117+SELECT * FROM t2;
118+--error ER_ERROR_DURING_COMMIT
119+SELECT * FROM t3;
120+
121+--error ER_ERROR_DURING_COMMIT
122+INSERT INTO t1 VALUES (2,2);
123+--error ER_ERROR_DURING_COMMIT
124+INSERT INTO t2 VALUES (2,2);
125+--error ER_ERROR_DURING_COMMIT
126+INSERT INTO t3 VALUES (2,lpad('a',10000, 'b'));
127+
128+--error ER_ERROR_DURING_COMMIT
129+UPDATE t1 SET a=0 where b=1;
130+--error ER_ERROR_DURING_COMMIT
131+UPDATE t2 SET a=0 where b=1;
132+--error ER_ERROR_DURING_COMMIT
133+UPDATE t3 SET a=0 where a=1;
134+
135+--error ER_ERROR_DURING_COMMIT
136+UPDATE t1 SET b=0 where a=1;
137+--error ER_ERROR_DURING_COMMIT
138+UPDATE t2 SET b=0 where a=1;
139+--error ER_ERROR_DURING_COMMIT
140+UPDATE t2 SET b=lpad('a',10000, 'z') where a=1;
141+
142+--error ER_ERROR_DURING_COMMIT
143+UPDATE t1 SET b=0 where a=2;
144+--error ER_ERROR_DURING_COMMIT
145+UPDATE t2 SET b=0 where a=2;
146+--error ER_ERROR_DURING_COMMIT
147+UPDATE t2 SET b=lpad('a',10000, 'z') where a=2;
148+
149+--error ER_ERROR_DURING_COMMIT
150+DELETE FROM t1 where b=2;
151+--error ER_ERROR_DURING_COMMIT
152+DELETE FROM t2 where b=2;
153+
154+--error ER_ERROR_DURING_COMMIT
155+DELETE FROM t1 where a=2;
156+--error ER_ERROR_DURING_COMMIT
157+DELETE FROM t2 where a=2;
158+--error ER_ERROR_DURING_COMMIT
159+DELETE FROM t3 where a=2;
160+
161+--error ER_ERROR_DURING_COMMIT
162+REPLACE INTO t1 values (2,3);
163+--error ER_ERROR_DURING_COMMIT
164+REPLACE INTO t2 values (2,3);
165+--error ER_ERROR_DURING_COMMIT
166+REPLACE INTO t3 values (2,lpad('a',9000,'q'));
167+
168+--error ER_ERROR_DURING_COMMIT
169+INSERT INTO t1 VALUES (1,1) ON DUPLICATE KEY UPDATE b=2;
170+--error ER_ERROR_DURING_COMMIT
171+INSERT INTO t2 VALUES (1,1) ON DUPLICATE KEY UPDATE b=2;
172+--error ER_ERROR_DURING_COMMIT
173+INSERT INTO t3 VALUES (1,1) ON DUPLICATE KEY UPDATE b=lpad('b',11000,'c');
174+
175+--source include/show_binlog_events.inc
176+
177+let $binlog_pos_2= query_get_value("SHOW MASTER STATUS", Position, 1);
178+
179+--disable_query_log
180+eval SELECT $binlog_pos_1 = $binlog_pos_2 as must_be_1;
181+--enable_query_log
182+
183+SET innodb_fake_changes=default;
184+
185+DROP TABLE t1;
186+DROP TABLE t2;
187+DROP TABLE t3;
188
189=== modified file 'Percona-Server/sql/handler.cc'
190--- Percona-Server/sql/handler.cc 2013-06-27 15:35:20 +0000
191+++ Percona-Server/sql/handler.cc 2013-08-22 13:22:00 +0000
192@@ -1180,6 +1180,18 @@
193 {
194 if (ha_info->is_trx_read_write())
195 ++rw_ha_count;
196+ else
197+ {
198+ /*
199+ If we have any fake changes handlertons, they will not be marked as
200+ read-write, potentially skipping 2PC and causing the fake transaction
201+ to be binlogged. Force using 2PC in this case by bumping rw_ha_count
202+ for each fake changes handlerton.
203+ */
204+ handlerton *ht= ha_info->ht();
205+ if (unlikely(ht->is_fake_change && ht->is_fake_change(ht, thd)))
206+ ++rw_ha_count;
207+ }
208
209 if (! all)
210 {
211@@ -1348,7 +1360,14 @@
212 transaction is read-only. This allows for simpler
213 implementation in engines that are always read-only.
214 */
215- if (! hi->is_trx_read_write())
216+ /*
217+ But do call two-phase commit if the handlerton has fake changes
218+ enabled even if it's not marked as read-write. This will ensure that
219+ the fake changes handlerton prepare will fail, preventing binlogging
220+ and committing the transaction in other engines.
221+ */
222+ if (! hi->is_trx_read_write()
223+ && !(ht->is_fake_change && ht->is_fake_change(ht, thd)))
224 continue;
225 /*
226 Sic: we know that prepare() is not NULL since otherwise
227
228=== modified file 'Percona-Server/sql/handler.h'
229--- Percona-Server/sql/handler.h 2013-01-22 16:32:44 +0000
230+++ Percona-Server/sql/handler.h 2013-08-22 13:22:00 +0000
231@@ -844,6 +844,7 @@
232 enum enum_schema_tables);
233 my_bool (*flush_changed_page_bitmaps)(void);
234 my_bool (*purge_changed_page_bitmaps)(ulonglong lsn);
235+ my_bool (*is_fake_change)(handlerton *hton, THD *thd);
236 uint32 flags; /* global handler flags */
237 /*
238 Those handlerton functions below are properly initialized at handler
239
240=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
241--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-14 03:52:04 +0000
242+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-22 13:22:00 +0000
243@@ -459,6 +459,19 @@
244 /*================================*/
245 ulonglong lsn); /*!< in: LSN to purge files up to */
246
247+
248+/*****************************************************************//**
249+Check whether this is a fake change transaction.
250+@return TRUE if a fake change transaction */
251+static
252+my_bool
253+innobase_is_fake_change(
254+/*====================*/
255+ handlerton *hton, /*!< in: InnoDB handlerton */
256+ THD* thd); /*!< in: MySQL thread handle of the user for
257+ whom the transaction is being committed */
258+
259+
260 static const char innobase_hton_name[]= "InnoDB";
261
262 /*************************************************************//**
263@@ -2659,6 +2672,7 @@
264 = innobase_flush_changed_page_bitmaps;
265 innobase_hton->purge_changed_page_bitmaps
266 = innobase_purge_changed_page_bitmaps;
267+ innobase_hton->is_fake_change = innobase_is_fake_change;
268
269 ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
270
271@@ -3345,6 +3359,23 @@
272 return (my_bool)log_online_purge_changed_page_bitmaps(lsn);
273 }
274
275+/*****************************************************************//**
276+Check whether this is a fake change transaction.
277+@return TRUE if a fake change transaction */
278+static
279+my_bool
280+innobase_is_fake_change(
281+/*====================*/
282+ handlerton *hton __attribute__((unused)),
283+ /*!< in: InnoDB handlerton */
284+ THD* thd) /*!< in: MySQL thread handle of the user for
285+ whom the transaction is being committed */
286+{
287+ trx_t* trx = check_trx_exists(thd);
288+ return trx->fake_changes;
289+}
290+
291+
292 /****************************************************************//**
293 Copy the current replication position from MySQL to a transaction. */
294 static
295@@ -11554,7 +11585,14 @@
296 return(0);
297 }
298
299- if (trx->fake_changes) {
300+ if (UNIV_UNLIKELY(trx->fake_changes)) {
301+
302+ if (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT
303+ | OPTION_BEGIN))) {
304+
305+ thd->stmt_da->reset_diagnostics_area();
306+ return(HA_ERR_WRONG_COMMAND);
307+ }
308 return(0);
309 }
310

Subscribers

People subscribed via source and target branches