Merge lp:~laurynas-biveinis/percona-server/bug1012715-5.5 into lp:percona-server/5.5
- bug1012715-5.5
- Merge into 5.5
Proposed by
Laurynas Biveinis
Status: | Merged |
---|---|
Approved by: | Alexey Kopytov |
Approved revision: | no longer in the source branch. |
Merged at revision: | 329 |
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
Review via email: mp+120043@code.launchpad.net |
This proposal supersedes a proposal from 2012-06-29.
Commit message
Description of the change
Merge bug 1012715 fix from 5.1 manually.
http://
Issue 22478
To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal | # |
review:
Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Please ping me if you are about to review this.
Revision history for this message
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/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-17 02:53:37 +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-17 02:53:37 +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-17 02:53:37 +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-17 02:53:37 +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-17 02:53:37 +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-17 02:53:37 +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-17 02:53:37 +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 |
Same comments as in the 5.1 MP.