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

Proposed by Laurynas Biveinis
Status: Superseded
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) Needs Fixing
Vlad Lesin (community) g2 Approve
Review via email: mp+170784@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.5.

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

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:42:36 +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-22 13:42:36 +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-22 13:42:36 +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-22 13:42:36 +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-22 13:42:36 +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