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

Proposed by Laurynas Biveinis on 2013-08-23
Status: Merged
Approved by: Alexey Kopytov on 2013-08-23
Approved revision: 414
Merged at revision: 414
Proposed branch: lp:~laurynas-biveinis/percona-server/fake-changes-binlog-5.6
Merge into: lp:percona-server/5.6
Diff against target: 308 lines (+237/-2)
5 files modified
Percona-Server/mysql-test/suite/binlog/r/binlog_percona_fake_changes.result (+71/-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.6
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) 2013-08-23 Approve on 2013-08-23
Vlad Lesin g2 2013-08-23 Pending
Review via email: mp+181712@code.launchpad.net

This proposal supersedes a proposal from 2013-06-21.

Description of the change

2nd MP:

http://jenkins.percona.com/job/percona-server-5.6-param/229/

1st MP:

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.5.

http://jenkins.percona.com/job/percona-server-5.6-param/154/

To post a comment you must log in.
Vlad Lesin (vlad-lesin) : Posted in a previous version of this proposal
review: Approve (g2)
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

Same comments as in 5.1.

review: Needs Fixing
Alexey Kopytov (akopytov) :
review: Approve

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-23 05:57:23 +0000
4@@ -0,0 +1,71 @@
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+include/show_binlog_events.inc
70+must_be_1
71+1
72+SET innodb_fake_changes=default;
73+DROP TABLE t1;
74+DROP TABLE t2;
75+DROP TABLE t3;
76
77=== added file 'Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test'
78--- Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test 1970-01-01 00:00:00 +0000
79+++ Percona-Server/mysql-test/suite/binlog/t/binlog_percona_fake_changes.test 2013-08-23 05:57:23 +0000
80@@ -0,0 +1,106 @@
81+#
82+# Test that fake changes are not written to binlog
83+# Based on rpl_percona_fake_changes.test in Facebook patch
84+# https://bugs.launchpad.net/percona-server/+bug/1190580
85+# https://bugs.launchpad.net/percona-server/+bug/1188162
86+#
87+
88+--source include/have_log_bin.inc
89+--source include/have_innodb.inc
90+
91+--disable_warnings
92+DROP TABLE IF EXISTS t1;
93+DROP TABLE IF EXISTS t2;
94+DROP TABLE IF EXISTS t3;
95+--enable_warnings
96+
97+CREATE TABLE t1 (a INT PRIMARY KEY, b int) ENGINE=InnoDB;
98+INSERT INTO t1 VALUES (1,1);
99+
100+CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE=InnoDB;
101+CREATE INDEX bx ON t2(b);
102+INSERT INTO t2 VALUES (1,1);
103+
104+CREATE TABLE t3 (a INT PRIMARY KEY, b text) ENGINE=InnoDB;
105+INSERT INTO t3 VALUES (1,'');
106+
107+RESET MASTER;
108+
109+let $binlog_pos_1= query_get_value("SHOW MASTER STATUS", Position, 1);
110+
111+SET innodb_fake_changes=1;
112+
113+--error ER_ERROR_DURING_COMMIT
114+SELECT * FROM t1;
115+--error ER_ERROR_DURING_COMMIT
116+SELECT * FROM t2;
117+--error ER_ERROR_DURING_COMMIT
118+SELECT * FROM t3;
119+
120+--error ER_ERROR_DURING_COMMIT
121+INSERT INTO t1 VALUES (2,2);
122+--error ER_ERROR_DURING_COMMIT
123+INSERT INTO t2 VALUES (2,2);
124+--error ER_ERROR_DURING_COMMIT
125+INSERT INTO t3 VALUES (2,lpad('a',10000, 'b'));
126+
127+--error ER_ERROR_DURING_COMMIT
128+UPDATE t1 SET a=0 where b=1;
129+--error ER_ERROR_DURING_COMMIT
130+UPDATE t2 SET a=0 where b=1;
131+--error ER_ERROR_DURING_COMMIT
132+UPDATE t3 SET a=0 where a=1;
133+
134+--error ER_ERROR_DURING_COMMIT
135+UPDATE t1 SET b=0 where a=1;
136+--error ER_ERROR_DURING_COMMIT
137+UPDATE t2 SET b=0 where a=1;
138+--error ER_ERROR_DURING_COMMIT
139+UPDATE t2 SET b=lpad('a',10000, 'z') where a=1;
140+
141+--error ER_ERROR_DURING_COMMIT
142+UPDATE t1 SET b=0 where a=2;
143+--error ER_ERROR_DURING_COMMIT
144+UPDATE t2 SET b=0 where a=2;
145+--error ER_ERROR_DURING_COMMIT
146+UPDATE t2 SET b=lpad('a',10000, 'z') where a=2;
147+
148+--error ER_ERROR_DURING_COMMIT
149+DELETE FROM t1 where b=2;
150+--error ER_ERROR_DURING_COMMIT
151+DELETE FROM t2 where b=2;
152+
153+--error ER_ERROR_DURING_COMMIT
154+DELETE FROM t1 where a=2;
155+--error ER_ERROR_DURING_COMMIT
156+DELETE FROM t2 where a=2;
157+--error ER_ERROR_DURING_COMMIT
158+DELETE FROM t3 where a=2;
159+
160+--error ER_ERROR_DURING_COMMIT
161+REPLACE INTO t1 values (2,3);
162+--error ER_ERROR_DURING_COMMIT
163+REPLACE INTO t2 values (2,3);
164+--error ER_ERROR_DURING_COMMIT
165+REPLACE INTO t3 values (2,lpad('a',9000,'q'));
166+
167+--error ER_ERROR_DURING_COMMIT
168+INSERT INTO t1 VALUES (1,1) ON DUPLICATE KEY UPDATE b=2;
169+--error ER_ERROR_DURING_COMMIT
170+INSERT INTO t2 VALUES (1,1) ON DUPLICATE KEY UPDATE b=2;
171+--error ER_ERROR_DURING_COMMIT
172+INSERT INTO t3 VALUES (1,1) ON DUPLICATE KEY UPDATE b=lpad('b',11000,'c');
173+
174+--source include/show_binlog_events.inc
175+
176+let $binlog_pos_2= query_get_value("SHOW MASTER STATUS", Position, 1);
177+
178+--disable_query_log
179+eval SELECT $binlog_pos_1 = $binlog_pos_2 as must_be_1;
180+--enable_query_log
181+
182+SET innodb_fake_changes=default;
183+
184+DROP TABLE t1;
185+DROP TABLE t2;
186+DROP TABLE t3;
187
188=== modified file 'Percona-Server/sql/handler.cc'
189--- Percona-Server/sql/handler.cc 2013-08-14 03:57:21 +0000
190+++ Percona-Server/sql/handler.cc 2013-08-23 05:57:23 +0000
191@@ -1298,6 +1298,18 @@
192 {
193 if (ha_info->is_trx_read_write())
194 ++rw_ha_count;
195+ else
196+ {
197+ /*
198+ If we have any fake changes handlertons, they will not be marked as
199+ read-write, potentially skipping 2PC and causing the fake transaction
200+ to be binlogged. Force using 2PC in this case by bumping rw_ha_count
201+ for each fake changes handlerton.
202+ */
203+ handlerton *ht= ha_info->ht();
204+ if (unlikely(ht->is_fake_change && ht->is_fake_change(ht, thd)))
205+ ++rw_ha_count;
206+ }
207
208 if (! all)
209 {
210@@ -2079,7 +2091,14 @@
211 transaction is read-only. This allows for simpler
212 implementation in engines that are always read-only.
213 */
214- if (!ha_info->is_trx_read_write())
215+ /*
216+ But do call two-phase commit if the handlerton has fake changes
217+ enabled even if it's not marked as read-write. This will ensure that
218+ the fake changes handlerton prepare will fail, preventing binlogging
219+ and committing the transaction in other engines.
220+ */
221+ if (!ha_info->is_trx_read_write()
222+ && !(ht->is_fake_change && ht->is_fake_change(ht, thd)))
223 continue;
224 if ((err= ht->prepare(ht, thd, all)))
225 {
226
227=== modified file 'Percona-Server/sql/handler.h'
228--- Percona-Server/sql/handler.h 2013-08-06 15:16:34 +0000
229+++ Percona-Server/sql/handler.h 2013-08-23 05:57:23 +0000
230@@ -894,6 +894,7 @@
231 my_bool (*purge_changed_page_bitmaps)(ulonglong lsn);
232 bool (*purge_archive_logs)(handlerton *hton, time_t before_date,
233 const char* to_filename);
234+ my_bool (*is_fake_change)(handlerton *hton, THD *thd);
235
236 uint32 flags; /* global handler flags */
237 /*
238
239=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
240--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-14 03:57:21 +0000
241+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-23 05:57:23 +0000
242@@ -522,6 +522,19 @@
243 /*================================*/
244 ulonglong lsn); /*!< in: LSN to purge files up to */
245
246+
247+/*****************************************************************//**
248+Check whether this is a fake change transaction.
249+@return TRUE if a fake change transaction */
250+static
251+my_bool
252+innobase_is_fake_change(
253+/*====================*/
254+ handlerton *hton, /*!< in: InnoDB handlerton */
255+ THD* thd); /*!< in: MySQL thread handle of the user for
256+ whom the transaction is being committed */
257+
258+
259 static const char innobase_hton_name[]= "InnoDB";
260
261 static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
262@@ -2997,6 +3010,7 @@
263 = innobase_flush_changed_page_bitmaps;
264 innobase_hton->purge_changed_page_bitmaps
265 = innobase_purge_changed_page_bitmaps;
266+ innobase_hton->is_fake_change = innobase_is_fake_change;
267
268 ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
269
270@@ -3654,6 +3668,22 @@
271 }
272
273 /*****************************************************************//**
274+Check whether this is a fake change transaction.
275+@return TRUE if a fake change transaction */
276+static
277+my_bool
278+innobase_is_fake_change(
279+/*====================*/
280+ handlerton *hton __attribute__((unused)),
281+ /*!< in: InnoDB handlerton */
282+ THD* thd) /*!< in: MySQL thread handle of the user for
283+ whom the transaction is being committed */
284+{
285+ trx_t* trx = check_trx_exists(thd);
286+ return trx->fake_changes;
287+}
288+
289+/*****************************************************************//**
290 Commits a transaction in an InnoDB database. */
291 static
292 void
293@@ -13939,7 +13969,15 @@
294 return(0);
295 }
296
297- if (trx->fake_changes) {
298+ if (UNIV_UNLIKELY(trx->fake_changes)) {
299+
300+ if (prepare_trx
301+ || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT
302+ | OPTION_BEGIN))) {
303+
304+ thd->get_stmt_da()->reset_diagnostics_area();
305+ return(HA_ERR_WRONG_COMMAND);
306+ }
307 return(0);
308 }
309

Subscribers

People subscribed via source and target branches