Merge lp:~laurynas-biveinis/percona-server/bug1012715-5.5 into lp:percona-server/5.5

Proposed by Laurynas Biveinis
Status: Superseded
Proposed branch: lp:~laurynas-biveinis/percona-server/bug1012715-5.5
Merge into: lp:percona-server/5.5
Diff against target: 869 lines (+523/-165)
7 files modified
Percona-Server/mysql-test/suite/rpl/r/rpl_percona_crash_resistant_rpl.result (+54/-0)
Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt (+1/-0)
Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test (+117/-0)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+221/-108)
Percona-Server/storage/innobase/include/trx0sys.h (+15/-1)
Percona-Server/storage/innobase/trx/trx0sys.c (+96/-54)
Percona-Server/storage/innobase/trx/trx0trx.c (+19/-2)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-server/bug1012715-5.5
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Needs Fixing
Review via email: mp+112691@code.launchpad.net

This proposal has been superseded by a proposal from 2012-08-17.

Description of the change

To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Same comments as in the 5.1 MP.

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/rpl/r/rpl_percona_crash_resistant_rpl.result'
2--- Percona-Server/mysql-test/suite/rpl/r/rpl_percona_crash_resistant_rpl.result 1970-01-01 00:00:00 +0000
3+++ Percona-Server/mysql-test/suite/rpl/r/rpl_percona_crash_resistant_rpl.result 2012-08-16 13:52:04 +0000
4@@ -0,0 +1,54 @@
5+include/master-slave.inc
6+[connection master]
7+DROP TABLE IF EXISTS t1;
8+CREATE TABLE t1 (id INT(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)) ENGINE=InnoDB;
9+INSERT INTO t1 VALUES ();
10+SELECT COUNT(*) FROM t1;
11+COUNT(*)
12+1
13+include/rpl_restart_server.inc [server_number=2]
14+include/start_slave.inc
15+SELECT COUNT(*) FROM t1;
16+COUNT(*)
17+1
18+STOP SLAVE;
19+include/wait_for_slave_to_stop.inc
20+INSERT INTO t1 VALUES();
21+SELECT COUNT(*) FROM t1;
22+COUNT(*)
23+2
24+SET GLOBAL debug="+d,crash_commit_before";
25+START SLAVE;
26+include/rpl_start_server.inc [server_number=2]
27+include/start_slave.inc
28+SELECT COUNT(*) FROM t1;
29+COUNT(*)
30+2
31+STOP SLAVE;
32+include/wait_for_slave_to_stop.inc
33+INSERT INTO t1 VALUES();
34+SELECT COUNT(*) FROM t1;
35+COUNT(*)
36+3
37+SET GLOBAL debug="+d,crash_innodb_after_prepare";
38+START SLAVE;
39+include/rpl_start_server.inc [server_number=2]
40+include/start_slave.inc
41+SELECT COUNT(*) FROM t1;
42+COUNT(*)
43+3
44+STOP SLAVE;
45+include/wait_for_slave_to_stop.inc
46+INSERT INTO t1 VALUES();
47+SELECT COUNT(*) FROM t1;
48+COUNT(*)
49+4
50+SET GLOBAL debug="+d,crash_innodb_before_commit";
51+START SLAVE;
52+include/rpl_start_server.inc [server_number=2]
53+include/start_slave.inc
54+SELECT COUNT(*) FROM t1;
55+COUNT(*)
56+4
57+DROP TABLE t1;
58+include/rpl_end.inc
59
60=== added file 'Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt'
61--- Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt 1970-01-01 00:00:00 +0000
62+++ Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt 2012-08-16 13:52:04 +0000
63@@ -0,0 +1,1 @@
64+--innodb-recovery-update-relay-log=TRUE --skip-core-file --skip-stack-trace
65
66=== added file 'Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test'
67--- Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test 1970-01-01 00:00:00 +0000
68+++ Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test 2012-08-16 13:52:04 +0000
69@@ -0,0 +1,117 @@
70+# Tests for Percona crash-resistant replication feature
71+--source include/have_innodb.inc
72+--source include/master-slave.inc
73+--source include/not_valgrind.inc
74+--source include/not_crashrep.inc
75+--source include/have_debug.inc
76+
77+#
78+# Setup
79+#
80+
81+--disable_query_log
82+call mtr.add_suppression("InnoDB: Warning: innodb_overwrite_relay_log_info is enabled.");
83+--enable_query_log
84+
85+connection master;
86+
87+--disable_warnings
88+DROP TABLE IF EXISTS t1;
89+--enable_warnings
90+
91+CREATE TABLE t1 (id INT(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)) ENGINE=InnoDB;
92+
93+#
94+# Test the non-crashing case
95+#
96+
97+INSERT INTO t1 VALUES ();
98+SELECT COUNT(*) FROM t1;
99+
100+sync_slave_with_master;
101+--let $rpl_server_number= 2
102+--source include/rpl_restart_server.inc
103+--source include/start_slave.inc
104+SELECT COUNT(*) FROM t1;
105+
106+#
107+# Test the crashing case where relay-log.info needs not to be overwritten
108+#
109+
110+STOP SLAVE;
111+--source include/wait_for_slave_to_stop.inc
112+
113+connection master;
114+INSERT INTO t1 VALUES();
115+SELECT COUNT(*) FROM t1;
116+
117+connection slave;
118+SET GLOBAL debug="+d,crash_commit_before";
119+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
120+--error 0,2013
121+START SLAVE;
122+--source include/wait_until_disconnected.inc
123+--enable_reconnect
124+
125+--let $rpl_server_number= 2
126+--source include/rpl_start_server.inc
127+--source include/start_slave.inc
128+connection master;
129+sync_slave_with_master;
130+SELECT COUNT(*) FROM t1;
131+
132+#
133+# Test the rollback of slave position stored in the InnoDB trx header.
134+#
135+STOP SLAVE;
136+--source include/wait_for_slave_to_stop.inc
137+
138+connection master;
139+INSERT INTO t1 VALUES();
140+SELECT COUNT(*) FROM t1;
141+
142+connection slave;
143+SET GLOBAL debug="+d,crash_innodb_after_prepare";
144+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
145+--error 0,2013
146+START SLAVE;
147+--source include/wait_until_disconnected.inc
148+--enable_reconnect
149+
150+--let $rpl_server_number= 2
151+--source include/rpl_start_server.inc
152+--source include/start_slave.inc
153+connection master;
154+sync_slave_with_master;
155+SELECT COUNT(*) FROM t1;
156+
157+#
158+# Test crash with XA transaction recovery (bug 1012715)
159+#
160+STOP SLAVE;
161+--source include/wait_for_slave_to_stop.inc
162+connection master;
163+INSERT INTO t1 VALUES();
164+SELECT COUNT(*) FROM t1;
165+
166+connection slave;
167+SET GLOBAL debug="+d,crash_innodb_before_commit";
168+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
169+--error 0,2013
170+START SLAVE;
171+--source include/wait_until_disconnected.inc
172+--enable_reconnect
173+
174+--let $rpl_server_number= 2
175+--source include/rpl_start_server.inc
176+--source include/start_slave.inc
177+SELECT COUNT(*) FROM t1;
178+
179+#
180+# Cleanup
181+#
182+
183+connection master;
184+DROP TABLE t1;
185+
186+--source include/rpl_end.inc
187
188=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
189--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2012-08-07 06:10:00 +0000
190+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2012-08-16 13:52:04 +0000
191@@ -2483,6 +2483,118 @@
192 reset_template(prebuilt);
193 }
194
195+/* The last read master log coordinates in the slave info file */
196+static char master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
197+static int master_log_pos;
198+/* The slave relay log coordinates in the slave info file after startup */
199+static char original_relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
200+static int original_relay_log_pos;
201+/* The master log coordinates in the slave info file after startup */
202+static char original_master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
203+static int original_master_log_pos;
204+
205+/*****************************************************************//**
206+Overwrites the MySQL relay log info file with the current master and relay log
207+coordinates from InnoDB. Skips overwrite if the master log position did not
208+change from the last overwrite. If the InnoDB master log position is equal
209+to position that was read from the info file on startup before any overwrites,
210+restores the original positions. */
211+static
212+void
213+innobase_do_overwrite_relay_log_info(void)
214+/*======================================*/
215+{
216+ char info_fname[FN_REFLEN];
217+ File info_fd = -1;
218+ int error = 0;
219+ char buff[FN_REFLEN*2+22*2+4];
220+ char *relay_info_log_pos;
221+ size_t buf_len;
222+
223+ if (master_log_fname[0] == '\0') {
224+ fprintf(stderr,
225+ "InnoDB: something wrong with relay-log.info. "
226+ "InnoDB will not overwrite it.\n");
227+ return;
228+ }
229+
230+ if (strcmp(master_log_fname, trx_sys_mysql_master_log_name) == 0
231+ && master_log_pos == trx_sys_mysql_master_log_pos) {
232+ fprintf(stderr,
233+ "InnoDB: InnoDB and relay-log.info are synchronized. "
234+ "InnoDB will not overwrite it.\n");
235+ return;
236+ }
237+
238+ /* If we overwrite the file back to the original master log position,
239+ restore the original relay log position too. This is required because
240+ we might have rolled back a prepared transaction and restored the
241+ original master log position from the InnoDB trx sys header, but the
242+ corresponding relay log position points to an already-purged file. */
243+ if (strcmp(original_master_log_fname, trx_sys_mysql_master_log_name)
244+ == 0
245+ && (original_master_log_pos == trx_sys_mysql_master_log_pos)) {
246+
247+ strncpy(trx_sys_mysql_relay_log_name, original_relay_log_fname,
248+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
249+ trx_sys_mysql_relay_log_pos = original_relay_log_pos;
250+ }
251+
252+ fn_format(info_fname, relay_log_info_file, mysql_data_home, "",
253+ MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH);
254+
255+ if (access(info_fname, F_OK)) {
256+ /* File does not exist */
257+ error = 1;
258+ goto skip_overwrite;
259+ }
260+
261+ /* File exists */
262+ info_fd = my_open(info_fname, O_RDWR|O_BINARY, MYF(MY_WME));
263+ if (info_fd < 0) {
264+ error = 1;
265+ goto skip_overwrite;
266+ }
267+
268+ relay_info_log_pos = strmov(buff, trx_sys_mysql_relay_log_name);
269+ *relay_info_log_pos ++= '\n';
270+ relay_info_log_pos = longlong2str(trx_sys_mysql_relay_log_pos,
271+ relay_info_log_pos, 10);
272+ *relay_info_log_pos ++= '\n';
273+ relay_info_log_pos = strmov(relay_info_log_pos,
274+ trx_sys_mysql_master_log_name);
275+ *relay_info_log_pos ++= '\n';
276+ relay_info_log_pos = longlong2str(trx_sys_mysql_master_log_pos,
277+ relay_info_log_pos, 10);
278+ *relay_info_log_pos = '\n';
279+
280+ buf_len = (relay_info_log_pos - buff) + 1;
281+ if (my_write(info_fd, (uchar *)buff, buf_len, MY_WME) != buf_len) {
282+ error = 1;
283+ } else if (my_sync(info_fd, MY_WME)) {
284+ error = 1;
285+ }
286+
287+ if (info_fd >= 0) {
288+ my_close(info_fd, MYF(0));
289+ }
290+
291+ strncpy(master_log_fname, trx_sys_mysql_relay_log_name,
292+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
293+ master_log_pos = trx_sys_mysql_master_log_pos;
294+
295+skip_overwrite:
296+ if (error) {
297+ fprintf(stderr,
298+ "InnoDB: ERROR: error occured during overwriting "
299+ "relay-log.info.\n");
300+ } else {
301+ fprintf(stderr,
302+ "InnoDB: relay-log.info was overwritten.\n");
303+ }
304+}
305+
306+
307 /*********************************************************************//**
308 Opens an InnoDB database.
309 @return 0 on success, error code on failure */
310@@ -2617,12 +2729,13 @@
311 #ifdef HAVE_REPLICATION
312 #ifdef MYSQL_SERVER
313 /* read master log position from relay-log.info if exists */
314- char fname[FN_REFLEN+128];
315- int pos;
316+ char info_fname[FN_REFLEN];
317+ char relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
318+ int relay_log_pos;
319 int info_fd;
320 IO_CACHE info_file;
321
322- fname[0] = '\0';
323+ info_fname[0] = '\0';
324
325 if(innobase_overwrite_relay_log_info) {
326
327@@ -2631,13 +2744,14 @@
328 " Updates by other storage engines may not be synchronized.\n");
329
330 bzero((char*) &info_file, sizeof(info_file));
331- fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
332+ fn_format(info_fname, relay_log_info_file, mysql_data_home, "", 4+32);
333
334 int error=0;
335
336- if (!access(fname,F_OK)) {
337+ if (!access(info_fname,F_OK)) {
338 /* exist */
339- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
340+ if ((info_fd = my_open(info_fname, O_RDWR | O_BINARY,
341+ MYF(MY_WME))) < 0) {
342 error=1;
343 } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
344 READ_CACHE, 0L, 0, MYF(MY_WME))) {
345@@ -2648,16 +2762,18 @@
346 relay_info_error:
347 if (info_fd >= 0)
348 my_close(info_fd, MYF(0));
349- fname[0] = '\0';
350+ master_log_fname[0] = '\0';
351 goto skip_relay;
352 }
353 } else {
354- fname[0] = '\0';
355+ master_log_fname[0] = '\0';
356 goto skip_relay;
357 }
358
359- if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
360- init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
361+ if (init_strvar_from_file(relay_log_fname, sizeof(relay_log_fname),
362+ &info_file, "")
363+ || /* dummy (it is relay-log) */ init_intvar_from_file(
364+ &relay_log_pos, &info_file, BIN_LOG_HEADER_SIZE)) {
365 end_io_cache(&info_file);
366 error=1;
367 goto relay_info_error;
368@@ -2666,13 +2782,19 @@
369 fprintf(stderr,
370 "InnoDB: relay-log.info is detected.\n"
371 "InnoDB: relay log: position %u, file name %s\n",
372- pos, fname);
373-
374- strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
375- trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
376-
377- if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
378- init_intvar_from_file(&pos, &info_file, 0)) {
379+ relay_log_pos, relay_log_fname);
380+
381+ strncpy(trx_sys_mysql_relay_log_name, relay_log_fname,
382+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
383+ trx_sys_mysql_relay_log_pos = (ib_int64_t) relay_log_pos;
384+
385+ strncpy(original_relay_log_fname, relay_log_fname,
386+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
387+ original_relay_log_pos = relay_log_pos;
388+
389+ if (init_strvar_from_file(master_log_fname, sizeof(master_log_fname),
390+ &info_file, "")
391+ || init_intvar_from_file(&master_log_pos, &info_file, 0)) {
392 end_io_cache(&info_file);
393 error=1;
394 goto relay_info_error;
395@@ -2680,10 +2802,15 @@
396
397 fprintf(stderr,
398 "InnoDB: master log: position %u, file name %s\n",
399- pos, fname);
400-
401- strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
402- trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
403+ master_log_pos, master_log_fname);
404+
405+ strncpy(trx_sys_mysql_master_log_name, master_log_fname,
406+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
407+ trx_sys_mysql_master_log_pos = (ib_int64_t) master_log_pos;
408+
409+ strncpy(original_master_log_fname, master_log_fname,
410+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
411+ original_master_log_pos = master_log_pos;
412
413 end_io_cache(&info_file);
414 if (info_fd >= 0)
415@@ -3017,75 +3144,9 @@
416 goto mem_free_and_error;
417 }
418
419-#ifdef HAVE_REPLICATION
420-#ifdef MYSQL_SERVER
421 if(innobase_overwrite_relay_log_info) {
422- /* If InnoDB progressed from relay-log.info, overwrite it */
423- if (fname[0] == '\0') {
424- fprintf(stderr,
425- "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
426- } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
427- || pos != trx_sys_mysql_master_log_pos) {
428- /* Overwrite relay-log.info */
429- bzero((char*) &info_file, sizeof(info_file));
430- fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
431-
432- int error = 0;
433-
434- if (!access(fname,F_OK)) {
435- /* exist */
436- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
437- error = 1;
438- } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
439- WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
440- error = 1;
441- }
442-
443- if (error) {
444- if (info_fd >= 0)
445- my_close(info_fd, MYF(0));
446- goto skip_overwrite;
447- }
448- } else {
449- error = 1;
450- goto skip_overwrite;
451- }
452-
453- char buff[FN_REFLEN*2+22*2+4], *pos;
454-
455- my_b_seek(&info_file, 0L);
456- pos=strmov(buff, trx_sys_mysql_relay_log_name);
457- *pos++='\n';
458- pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
459- *pos++='\n';
460- pos=strmov(pos, trx_sys_mysql_master_log_name);
461- *pos++='\n';
462- pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
463- *pos='\n';
464-
465- if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
466- error = 1;
467- if (flush_io_cache(&info_file))
468- error = 1;
469-
470- end_io_cache(&info_file);
471- if (info_fd >= 0)
472- my_close(info_fd, MYF(0));
473-skip_overwrite:
474- if (error) {
475- fprintf(stderr,
476- "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
477- } else {
478- fprintf(stderr,
479- "InnoDB: The file relay-log.info was successfully overwritten.\n");
480- }
481- } else {
482- fprintf(stderr,
483- "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
484- }
485- }
486-#endif /* MYSQL_SERVER */
487-#endif /* HAVE_REPLICATION */
488+ innobase_do_overwrite_relay_log_info();
489+ }
490
491 innobase_old_blocks_pct = buf_LRU_old_ratio_update(
492 innobase_old_blocks_pct, TRUE);
493@@ -3191,6 +3252,32 @@
494 | HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE);
495 }
496
497+/****************************************************************//**
498+Copy the current replication position from MySQL to a transaction. */
499+static
500+void
501+innobase_copy_repl_coords_to_trx(
502+/*=============================*/
503+ const THD* thd, /*!< in: thread handle */
504+ trx_t* trx) /*!< in/out: transaction */
505+{
506+ if (thd && thd->slave_thread) {
507+ const Relay_log_info* rli = &active_mi->rli;
508+
509+ trx->mysql_master_log_file_name
510+ = rli->group_master_log_name;
511+ trx->mysql_master_log_pos
512+ = ((ib_int64_t)rli->group_master_log_pos
513+ + ((ib_int64_t)
514+ rli->future_event_relay_log_pos
515+ - (ib_int64_t)rli->group_relay_log_pos));
516+ trx->mysql_relay_log_file_name
517+ = rli->group_relay_log_name;
518+ trx->mysql_relay_log_pos
519+ = (ib_int64_t)rli->future_event_relay_log_pos;
520+ }
521+}
522+
523 /*****************************************************************//**
524 Commits a transaction in an InnoDB database. */
525 static
526@@ -3200,25 +3287,12 @@
527 trx_t* trx) /*!< in: transaction handle */
528 {
529 if (trx_is_started(trx)) {
530-#ifdef HAVE_REPLICATION
531-#ifdef MYSQL_SERVER
532- THD *thd=current_thd;
533-
534- if (thd && thd->slave_thread) {
535- /* Update the replication position info inside InnoDB */
536- trx->mysql_master_log_file_name
537- = active_mi->rli.group_master_log_name;
538- trx->mysql_master_log_pos
539- = ((ib_int64_t)active_mi->rli.group_master_log_pos +
540- ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
541- (ib_int64_t)active_mi->rli.group_relay_log_pos));
542- trx->mysql_relay_log_file_name
543- = active_mi->rli.group_relay_log_name;
544- trx->mysql_relay_log_pos
545- = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
546- }
547-#endif /* MYSQL_SERVER */
548-#endif /* HAVE_REPLICATION */
549+
550+ /* Save the current replication position for write to trx sys
551+ header for undo purposes, see the comment at corresponding call
552+ at innobase_xa_prepare(). */
553+
554+ innobase_copy_repl_coords_to_trx(current_thd, trx);
555
556 trx_commit_for_mysql(trx);
557 }
558@@ -3436,6 +3510,9 @@
559 if (all
560 || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
561
562+ DBUG_EXECUTE_IF("crash_innodb_before_commit",
563+ DBUG_SUICIDE(););
564+
565 /* We were instructed to commit the whole transaction, or
566 this is an SQL statement end and autocommit is on */
567
568@@ -11369,7 +11446,27 @@
569
570 ut_ad(trx_is_registered_for_2pc(trx));
571
572+ /* Update the replication position info in current trx. This
573+ is different from the binlog position update that happens
574+ during XA COMMIT. In contrast to that, the slave position is
575+ an actual part of the changes made by this transaction and thus
576+ must be updated in the XA PREPARE stage. Since the trx sys
577+ header page changes are not undo-logged, again store this
578+ position in a different field in the XA COMMIT stage, so that
579+ it might be used in case of rollbacks. */
580+
581+ /* Since currently there might be only one slave SQL thread, we
582+ don't need to take any precautions (e.g. prepare_commit_mutex)
583+ to ensure position ordering. Revisit this in 5.6 which has
584+ both the multi-threaded replication to cause us problems and
585+ the group commit to solve them. */
586+
587+ innobase_copy_repl_coords_to_trx(thd, trx);
588+
589 error = (int) trx_prepare_for_mysql(trx);
590+
591+ DBUG_EXECUTE_IF("crash_innodb_after_prepare",
592+ DBUG_SUICIDE(););
593 } else {
594 /* We just mark the SQL statement ended and do not do a
595 transaction prepare */
596@@ -11491,6 +11588,22 @@
597 if (trx) {
598 int ret = innobase_rollback_trx(trx);
599 trx_free_for_background(trx);
600+
601+ if (innobase_overwrite_relay_log_info) {
602+
603+ /* On rollback of a prepared transaction revert the
604+ current slave positions to the ones recorded by the
605+ last COMMITTed transaction. This has an effect of
606+ undoing the position change caused by the transaction
607+ being rolled back. Assumes single-threaded slave SQL
608+ thread. If the server has non-master write traffic
609+ with XA rollbacks, this will cause additional spurious
610+ slave info log overwrites, which should be harmless. */
611+
612+ trx_sys_print_committed_mysql_master_log_pos();
613+ innobase_do_overwrite_relay_log_info();
614+ }
615+
616 return(ret);
617 } else {
618 return(XAER_NOTA);
619
620=== modified file 'Percona-Server/storage/innobase/include/trx0sys.h'
621--- Percona-Server/storage/innobase/include/trx0sys.h 2012-08-07 06:10:00 +0000
622+++ Percona-Server/storage/innobase/include/trx0sys.h 2012-08-16 13:52:04 +0000
623@@ -342,6 +342,14 @@
624 trx_sys_print_mysql_binlog_offset(void);
625 /*===================================*/
626 /*****************************************************************//**
627+Prints to stderr the MySQL master log offset info in the trx system header
628+COMMIT set of fields if the magic number shows it valid and stores it
629+in global variables. */
630+UNIV_INTERN
631+void
632+trx_sys_print_committed_mysql_master_log_pos(void);
633+/*==============================================*/
634+/*****************************************************************//**
635 Prints to stderr the MySQL master log offset info in the trx system header if
636 the magic number shows it valid. */
637 UNIV_INTERN
638@@ -534,10 +542,16 @@
639 //# error "UNIV_PAGE_SIZE < 4096"
640 //#endif
641 /** The offset of the MySQL replication info in the trx system header;
642-this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
643+this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below. These are
644+written at prepare time and are the main copy. */
645 #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
646 #define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
647
648+/** The copy of the above which is made at transaction COMMIT time. If binlog
649+crash recovery rollbacks a PREPAREd transaction, they are copied back. */
650+#define TRX_SYS_COMMIT_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 3000)
651+#define TRX_SYS_COMMIT_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 2500)
652+
653 /** The offset of the MySQL binlog offset info in the trx system header */
654 #define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
655 #define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /*!< magic number which is
656
657=== modified file 'Percona-Server/storage/innobase/trx/trx0sys.c'
658--- Percona-Server/storage/innobase/trx/trx0sys.c 2012-08-07 06:10:00 +0000
659+++ Percona-Server/storage/innobase/trx/trx0sys.c 2012-08-16 13:52:04 +0000
660@@ -959,8 +959,31 @@
661 }
662
663 /*****************************************************************//**
664-Prints to stderr the MySQL master log offset info in the trx system header if
665-the magic number shows it valid. */
666+Reads the log coordinates at the given offset in the trx sys header. */
667+static
668+void
669+trx_sys_read_log_pos(
670+/*=================*/
671+ const trx_sysf_t* sys_header, /*!< in: the trx sys header */
672+ uint header_offset, /*!< in: coord offset in the
673+ header */
674+ char* log_fn, /*!< out: the log file name */
675+ ib_int64_t* log_pos) /*!< out: the log poistion */
676+{
677+ ut_memcpy(log_fn, sys_header + header_offset + TRX_SYS_MYSQL_LOG_NAME,
678+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
679+
680+ *log_pos =
681+ (((ib_int64_t)mach_read_from_4(sys_header + header_offset
682+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
683+ + mach_read_from_4(sys_header + header_offset
684+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW);
685+}
686+
687+/*****************************************************************//**
688+Prints to stderr the MySQL master log offset info in the trx system header
689+PREPARE set of fields if the magic number shows it valid and stores it
690+in global variables. */
691 UNIV_INTERN
692 void
693 trx_sys_print_mysql_master_log_pos(void)
694@@ -982,60 +1005,79 @@
695 return;
696 }
697
698- fprintf(stderr,
699- "InnoDB: In a MySQL replication slave the last"
700- " master binlog file\n"
701- "InnoDB: position %lu %lu, file name %s\n",
702- (ulong) mach_read_from_4(sys_header
703- + TRX_SYS_MYSQL_MASTER_LOG_INFO
704- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
705- (ulong) mach_read_from_4(sys_header
706- + TRX_SYS_MYSQL_MASTER_LOG_INFO
707- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
708- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
709- + TRX_SYS_MYSQL_LOG_NAME);
710-
711- fprintf(stderr,
712- "InnoDB: and relay log file\n"
713- "InnoDB: position %lu %lu, file name %s\n",
714- (ulong) mach_read_from_4(sys_header
715- + TRX_SYS_MYSQL_RELAY_LOG_INFO
716- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
717- (ulong) mach_read_from_4(sys_header
718- + TRX_SYS_MYSQL_RELAY_LOG_INFO
719- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
720- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
721- + TRX_SYS_MYSQL_LOG_NAME);
722-
723 /* Copy the master log position info to global variables we can
724 use in ha_innobase.cc to initialize glob_mi to right values */
725-
726- ut_memcpy(trx_sys_mysql_master_log_name,
727- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
728- + TRX_SYS_MYSQL_LOG_NAME,
729- TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
730-
731- trx_sys_mysql_master_log_pos
732- = (((ib_int64_t) mach_read_from_4(
733- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
734- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
735- + ((ib_int64_t) mach_read_from_4(
736- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
737- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
738-
739- ut_memcpy(trx_sys_mysql_relay_log_name,
740- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
741- + TRX_SYS_MYSQL_LOG_NAME,
742- TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
743-
744- trx_sys_mysql_relay_log_pos
745- = (((ib_int64_t) mach_read_from_4(
746- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
747- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
748- + ((ib_int64_t) mach_read_from_4(
749- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
750- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
751- mtr_commit(&mtr);
752+ trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_MASTER_LOG_INFO,
753+ trx_sys_mysql_master_log_name,
754+ &trx_sys_mysql_master_log_pos);
755+
756+ trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_RELAY_LOG_INFO,
757+ trx_sys_mysql_relay_log_name,
758+ &trx_sys_mysql_relay_log_pos);
759+
760+ mtr_commit(&mtr);
761+
762+ fprintf(stderr,
763+ "InnoDB: In a MySQL replication slave the last"
764+ " master binlog file\n"
765+ "InnoDB: position %llu, file name %s\n",
766+ trx_sys_mysql_master_log_pos,
767+ trx_sys_mysql_master_log_name);
768+
769+ fprintf(stderr,
770+ "InnoDB: and relay log file\n"
771+ "InnoDB: position %llu, file name %s\n",
772+ trx_sys_mysql_relay_log_pos,
773+ trx_sys_mysql_relay_log_name);
774+}
775+
776+/*****************************************************************//**
777+Prints to stderr the MySQL master log offset info in the trx system header
778+COMMIT set of fields if the magic number shows it valid and stores it
779+in global variables. */
780+UNIV_INTERN
781+void
782+trx_sys_print_committed_mysql_master_log_pos(void)
783+/*==============================================*/
784+{
785+ trx_sysf_t* sys_header;
786+ mtr_t mtr;
787+
788+ mtr_start(&mtr);
789+
790+ sys_header = trx_sysf_get(&mtr);
791+
792+ if (mach_read_from_4(sys_header + TRX_SYS_COMMIT_MASTER_LOG_INFO
793+ + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
794+ != TRX_SYS_MYSQL_LOG_MAGIC_N) {
795+
796+ mtr_commit(&mtr);
797+
798+ return;
799+ }
800+
801+ /* Copy the master log position info to global variables we can
802+ use in ha_innobase.cc to initialize glob_mi to right values */
803+ trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_MASTER_LOG_INFO,
804+ trx_sys_mysql_master_log_name,
805+ &trx_sys_mysql_master_log_pos);
806+
807+ trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_RELAY_LOG_INFO,
808+ trx_sys_mysql_relay_log_name,
809+ &trx_sys_mysql_relay_log_pos);
810+
811+ mtr_commit(&mtr);
812+
813+ fprintf(stderr,
814+ "InnoDB: In a MySQL replication slave the last"
815+ " master binlog file\n"
816+ "InnoDB: position %llu, file name %s\n",
817+ trx_sys_mysql_master_log_pos, trx_sys_mysql_master_log_name);
818+
819+ fprintf(stderr,
820+ "InnoDB: and relay log file\n"
821+ "InnoDB: position %llu, file name %s\n",
822+ trx_sys_mysql_relay_log_pos, trx_sys_mysql_relay_log_name);
823 }
824
825 /****************************************************************//**
826
827=== modified file 'Percona-Server/storage/innobase/trx/trx0trx.c'
828--- Percona-Server/storage/innobase/trx/trx0trx.c 2012-05-10 07:49:14 +0000
829+++ Percona-Server/storage/innobase/trx/trx0trx.c 2012-08-16 13:52:04 +0000
830@@ -939,13 +939,13 @@
831 sys_header,
832 trx->mysql_relay_log_file_name,
833 trx->mysql_relay_log_pos,
834- TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
835+ TRX_SYS_COMMIT_RELAY_LOG_INFO, &mtr);
836
837 trx_sys_update_mysql_binlog_offset(
838 sys_header,
839 trx->mysql_master_log_file_name,
840 trx->mysql_master_log_pos,
841- TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
842+ TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr);
843
844 trx->mysql_master_log_file_name = "";
845 }
846@@ -2051,6 +2051,23 @@
847
848 mutex_exit(&(rseg->mutex));
849
850+ if (trx->mysql_master_log_file_name[0] != '\0') {
851+ /* This database server is a MySQL replication slave */
852+ trx_sysf_t* sys_header = trx_sysf_get(&mtr);
853+
854+ trx_sys_update_mysql_binlog_offset(
855+ sys_header,
856+ trx->mysql_relay_log_file_name,
857+ trx->mysql_relay_log_pos,
858+ TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
859+ trx_sys_update_mysql_binlog_offset(
860+ sys_header,
861+ trx->mysql_master_log_file_name,
862+ trx->mysql_master_log_pos,
863+ TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
864+ trx->mysql_master_log_file_name = "";
865+ }
866+
867 /*--------------*/
868 mtr_commit(&mtr); /* This mtr commit makes the
869 transaction prepared in the file-based

Subscribers

People subscribed via source and target branches