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

Proposed by Laurynas Biveinis
Status: Merged
Approved by: Alexey Kopytov
Approved revision: no longer in the source branch.
Merged at revision: 496
Proposed branch: lp:~laurynas-biveinis/percona-server/bug1012715-5.1
Merge into: lp:percona-server/5.1
Diff against target: 878 lines (+527/-170)
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/innodb_plugin/handler/ha_innodb.cc (+225/-113)
Percona-Server/storage/innodb_plugin/include/trx0sys.h (+15/-1)
Percona-Server/storage/innodb_plugin/trx/trx0sys.c (+96/-54)
Percona-Server/storage/innodb_plugin/trx/trx0trx.c (+19/-2)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-server/bug1012715-5.1
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
Laurynas Biveinis Pending
Percona core Pending
Review via email: mp+120042@code.launchpad.net

This proposal supersedes a proposal from 2012-07-18.

Description of the change

Issue 22478.

Fix bug 1012715. See the revision commit message for the changes.

Changes from the previous MP: review comments implemented and addressed, a testcase instability issue fixed (typo in expectation file name).

Jenkins: http://jenkins.percona.com/job/percona-server-5.1-param/371/

To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

Found one issue myself.

The testcase has one sync bug: lines 88--91 do not sync slave with master first, thus might result in slave shutdown while slave SQL thread is still executing.

review: Needs Fixing
Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

Laurynas,

The assumption this patch is based on looks wrong to me, i.e.:

> + XA COMMIT. In contrast to that, the slave position is an
> + actual part of the changes made by this transaction and thus
> + must be updated in the XA PREPARE stage. */

A prepared transaction may either be committed or rolled back (see xarecover_handlerton()) depending on whether the corresponding record made it to the binary log (and if the binary log is used at all).

The correct solution would be to update slave coordinates when commiting the corresponding XA transaction on recovery, rather than moving the code storing slave coordinates to persistent storage from COMMIT to PREPARE stage. The problem is that slave coordinates are not available at the point, i.e. when committing prepared transactions on recovery.

I wonder if we can fix this by introducing another set of slave coordinates in the trx header. The we can only update those fields on PREPARE, and update the regular TRX_SYS_MYSQL_RELAY_LOG_INFO fields on COMMIT. On recovery, we could copy the "prepare" fields to "committed" ones and overwrite the relay log info file, *if* the PREPAREd transaction is being committed, e.g. in innobase_commit_by_xid(). What do you think?

Minor comments on the test case:
- do we really need the "rpl_" prefix in rpl_percona_crash_resistant_rpl.*?
- please use

SET GLOBAL debug="+d,keyword"

instead of

SET GLOBAL debug="d,keyword"

The latter breaks ./mtr --debug.

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal
Download full text (3.3 KiB)

Alexey -

Thanks. Could you please expand on your comment on why you think this assumption is wrong -

> The assumption this patch is based on looks wrong to me, i.e.:
>
> > + XA COMMIT. In contrast to that, the slave position is an
> > + actual part of the changes made by this transaction and thus
> > + must be updated in the XA PREPARE stage. */

because the following explanation matches my assumptions precisely:

> A prepared transaction may either be committed or rolled back (see
> xarecover_handlerton()) depending on whether the corresponding record made it
> to the binary log (and if the binary log is used at all).

Namely, why is the assumption "slave position update is a part of actual transaction changes" wrong in the light of this? If a prepared transaction is rolled back, the old slave position is restored from an undo seg. If it is 2pc-committed, the new slave position becomes permanent.

Maybe you view this fix as incomplete or working by chance because of the following (which is the actual action sequence that happens in this bug): on crash recovery the relay status log overwrite will happen before the XA rollback, thus the slave position will point to as if the transaction was fully committed. Then the transaction will be rolled back, (which would require overwriting relay status log with the old position) and replayed from the binlog, (which would require overwriting the relay status log position again, but binlog does not have the required info for that). This results in correct positions, although with a shortcut taken. The assumption here that all replicated InnoDB XA prepared transactions will be eventually committed. It is not perfect but IMHO "slave position is a part of transaction itself" is a step to the right direction.

> The correct solution would be to update slave coordinates when commiting the
> corresponding XA transaction on recovery, rather than moving the code storing
> slave coordinates to persistent storage from COMMIT to PREPARE stage. The
> problem is that slave coordinates are not available at the point, i.e. when
> committing prepared transactions on recovery.

Fully agreed modulus that ATM I think it's "one of the possible correct solutions."

> I wonder if we can fix this by introducing another set of slave coordinates in
> the trx header. The we can only update those fields on PREPARE, and update the
> regular TRX_SYS_MYSQL_RELAY_LOG_INFO fields on COMMIT. On recovery, we could
> copy the "prepare" fields to "committed" ones and overwrite the relay log info
> file, *if* the PREPAREd transaction is being committed, e.g. in
> innobase_commit_by_xid(). What do you think?

Upon the first thought it seems workable, however I would like to postpone further discussion until we agree on the previous point, because there are other bugs in crash-resistant replication bug too, fixing which might require implementing "transactional system table for slave relay log," and if we have to do that, then we should discuss such fixes as a whole.

> Minor comments on the test case:
> - do we really need the "rpl_" prefix in rpl_percona_crash_resistant_rpl.*?

Looks funny to me too...

Read more...

Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

On 07/03/2012 08:35 PM, Laurynas Biveinis wrote:
=> Namely, why is the assumption "slave position update is a part of
actual transaction changes" wrong in the light of this? If a prepared
transaction is rolled back, the old slave position is restored from an
undo seg. If it is 2pc-committed, the new slave position becomes permanent.
>

Right, it didn't occur to me that updates of the trx header fields are
done as a part of the current transaction. If they are rolled back when
a prepared transaction is rolled back, then the fix is correct. Can we
have it covered by the test case?

Though it's not clear then what the difference with the binlog position
update is, i.e. what following means:

> + /* Update the replication position info inside InnoDB. This is
> + different from the binlog position update that happens during
> + XA COMMIT. In contrast to that, the slave position is an

> Maybe you view this fix as incomplete or working by chance because of the following (which is the actual action sequence that happens in this bug): on crash recovery the relay status log overwrite will happen before the XA rollback, thus the slave position will point to as if the transaction was fully committed. Then the transaction will be rolled back, (which would require overwriting relay status log with the old position) and replayed from the binlog, (which would require overwriting the relay status log position again, but binlog does not have the required info for that). This results in correct positions, although with a shortcut taken. The assumption here that all replicated InnoDB XA prepared transactions will be eventually committed. It is not perfect but IMHO "slave position is a part of transaction itself" is a step to the right direction.
>

I don't understand this. When and how a replay from binlog of a rolled
back XA transaction occurs? If I'm not mistaken, a roll back happens
when the corresponding event is _not_ in the binary log (or binlog not
used at all).

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

> On 07/03/2012 08:35 PM, Laurynas Biveinis wrote:
> => Namely, why is the assumption "slave position update is a part of
> actual transaction changes" wrong in the light of this? If a prepared
> transaction is rolled back, the old slave position is restored from an
> undo seg. If it is 2pc-committed, the new slave position becomes permanent.
> >
>
> Right, it didn't occur to me that updates of the trx header fields are
> done as a part of the current transaction. If they are rolled back when
> a prepared transaction is rolled back, then the fix is correct. Can we
> have it covered by the test case?

Good idea, I will work on this if the points below are agreed upon. I will probably use the explicit XA syntax.

> Though it's not clear then what the difference with the binlog position
> update is, i.e. what following means:
>
> > + /* Update the replication position info inside InnoDB. This
> is
> > + different from the binlog position update that happens during
> > + XA COMMIT. In contrast to that, the slave position is an

My understanding is that binlog position record in InnoDB means "InnoDB transactions are committed (not prepared) up to this binlog position." Thus it cannot possibly go back and in contrast to the slave info log, it is not part of the transaction itself, but rather InnoDB/binlog metadata of sorts. I briefly experimented with moving this to PREPARE too and broke crash recovery even worse. I can research to provide more info if you want me to.

> > Maybe you view this fix as incomplete or working by chance because of the
> following (which is the actual action sequence that happens in this bug): on
> crash recovery the relay status log overwrite will happen before the XA
> rollback, thus the slave position will point to as if the transaction was
> fully committed. Then the transaction will be rolled back, (which would
> require overwriting relay status log with the old position) and replayed from
> the binlog, (which would require overwriting the relay status log position
> again, but binlog does not have the required info for that). This results in
> correct positions, although with a shortcut taken. The assumption here that
> all replicated InnoDB XA prepared transactions will be eventually committed.
> It is not perfect but IMHO "slave position is a part of transaction itself" is
> a step to the right direction.
> >
>
> I don't understand this. When and how a replay from binlog of a rolled
> back XA transaction occurs? If I'm not mistaken, a roll back happens
> when the corresponding event is _not_ in the binary log (or binlog not
> used at all).

Right, sorry, memory failed me. The transaction is never rolledback, it sits there in prepared state on crash recovery and is committed during the binlog crash recovery. The fix still works as designed.

Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

On 07/04/2012 05:50 PM, Laurynas Biveinis wrote:
>> On 07/03/2012 08:35 PM, Laurynas Biveinis wrote:
>> => Namely, why is the assumption "slave position update is a part of
>> actual transaction changes" wrong in the light of this? If a prepared
>> transaction is rolled back, the old slave position is restored from an
>> undo seg. If it is 2pc-committed, the new slave position becomes permanent.
>>>
>>
>> Right, it didn't occur to me that updates of the trx header fields are
>> done as a part of the current transaction. If they are rolled back when
>> a prepared transaction is rolled back, then the fix is correct. Can we
>> have it covered by the test case?
>
> Good idea, I will work on this if the points below are agreed upon. I will probably use the explicit XA syntax.
>

There are also existing injection sites that you may want to use, e.g.
crash_commit_after_prepare will crash the server after preparing a
transaction, but before writing a xid event to binlog, so that would
theoretically lead to a rollback on recovery.

>> Though it's not clear then what the difference with the binlog position
>> update is, i.e. what following means:
>>
>>> + /* Update the replication position info inside InnoDB. This
>> is
>>> + different from the binlog position update that happens during
>>> + XA COMMIT. In contrast to that, the slave position is an
>
> My understanding is that binlog position record in InnoDB means "InnoDB transactions are committed (not prepared) up to this binlog position." Thus it cannot possibly go back and in contrast to the slave info log, it is not part of the transaction itself, but rather InnoDB/binlog metadata of sorts. I briefly experimented with moving this to PREPARE too and broke crash recovery even worse. I can research to provide more info if you want me to.
>

OK, I see what you meant to say, no need for details. Thanks for
clarifications.

Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

Laurynas,

   - many lines exceed the 80 line width limit
   - it is a good practice to end replication test cases with "--source
     include/rpl_end.inc"
   - Yoda notation in comparisons ("0 == ...")
   - variable declarations in the middle of a block is C99 (i.e. more
     Windows incompatibilities)
   - unnecessary (char *) cast for the first argument in bzero()
   - I don't think we actually need IO_CACHE in
     innobase_do_overwrite_relay_log_info(). it's basically an enhanced
     version of fwrite() & friends, whereas we only want a single write
     of buff to the file.
   - no spaces around '=' sign in many places
   - no braces in single-statement if()s
   - in general, I would suggest to fix all of the above by leaving the
     (incorrectly formatted) code alone and not moving it into a
     separate function. That would save me about half an hour on reading
     and commenting on changes that are not really changes but rather
     moving the code around, and allow me to focus on what's really been
     changed.
   - same goes for fname -> info_fname renaming
   - otherwise the patch looks good, but in case you decide to follow my
     suggestion and revert unnecessary changes, I'd like to take another
     review round. It's too easy to miss important things with so much
     insignificant changes.

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

Alexey -

Thanks for the review

> - many lines exceed the 80 line width limit
> - it is a good practice to end replication test cases with "--source
> include/rpl_end.inc"
> - Yoda notation in comparisons ("0 == ...")

Noted.

> - variable declarations in the middle of a block is C99 (i.e. more
> Windows incompatibilities)

Isn't ha_innodb.cc C++? But I will fix them in any case.

> - unnecessary (char *) cast for the first argument in bzero()
> - I don't think we actually need IO_CACHE in
> innobase_do_overwrite_relay_log_info(). it's basically an enhanced
> version of fwrite() & friends, whereas we only want a single write
> of buff to the file.
> - no spaces around '=' sign in many places
> - no braces in single-statement if()s

Noted.

> - in general, I would suggest to fix all of the above by leaving the
> (incorrectly formatted) code alone and not moving it into a
> separate function. That would save me about half an hour on reading
> and commenting on changes that are not really changes but rather
> moving the code around, and allow me to focus on what's really been
> changed.
> - same goes for fname -> info_fname renaming

There are two places where I extracted new functions from existing code: in ha_innodb.cc and in trx0sys.c. Which one of them, or both, are you referring to? The trx0sys.c one I can revert, but IMHO it is easy to review too. Re. ha_innodb.cc changes, I have extracted innobase_do_overwrite_relay_log_info() because I needed to call it from another function as well and I don't see a good alternative to making a new function: if I copy pasted the code, I'd still need to adjust it heavily due to different local var context and the end result would be very close to innobase_do_overwrite_relay_log_info() anyway then. And I did the fname/pos variable rename & split, because these variables being repurposed five times is way beyond my pain threshold and extracted from innobase_setup() they stop working anyway.

Is there any way I can make the review easier with separate function? A separate MP with no functional changes perhaps?

Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

On 09.08.12 6:30, Laurynas Biveinis wrote:
>
> Isn't ha_innodb.cc C++? But I will fix them in any case.
>

Right, it's C++, sorry.

>> - in general, I would suggest to fix all of the above by leaving the
>> (incorrectly formatted) code alone and not moving it into a
>> separate function. That would save me about half an hour on reading
>> and commenting on changes that are not really changes but rather
>> moving the code around, and allow me to focus on what's really been
>> changed.
>> - same goes for fname -> info_fname renaming
>
> There are two places where I extracted new functions from existing code: in ha_innodb.cc and in trx0sys.c. Which one of them, or both, are you referring to? The trx0sys.c one I can revert, but IMHO it is easy to review too. Re. ha_innodb.cc changes, I have extracted innobase_do_overwrite_relay_log_info() because I needed to call it from another function as well and I don't see a good alternative to making a new function: if I copy pasted the code, I'd still need to adjust it heavily due to different local var context and the end result would be very close to innobase_do_overwrite_relay_log_info() anyway then. And I did the fname/pos variable rename & split, because these variables being repurposed five times is way beyond my pain threshold and extracted from innobase_setup() they stop working anyway.
>

I was referring to innobase_do_overwrite_relay_log_info().

The second call of the function looked like a part of the comment to me
when I grepped:

+ /* On rollback of a prepared transaction revert the
+ current slave positions to the ones recorded by the
+ last COMMITTed transaction. This has an effect of
+ undoing the position change caused by the transaction
+ being rolled back. Assumes single-threaded slave SQL
+ thread. If the server has non-master write traffic
+ with XA rollbacks, this will cause additional spurious
+ slave info log overwrites, which should be harmless. */
+ trx_sys_print_committed_mysql_master_log_pos();
+ innobase_do_overwrite_relay_log_info();

In the InnoDB code multi-line comments are usually separated from code
with blank lines. That is easier to read.

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
=== added file 'Percona-Server/mysql-test/suite/rpl/r/rpl_percona_crash_resistant_rpl.result'
--- Percona-Server/mysql-test/suite/rpl/r/rpl_percona_crash_resistant_rpl.result 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/rpl/r/rpl_percona_crash_resistant_rpl.result 2012-08-17 02:51:27 +0000
@@ -0,0 +1,54 @@
1include/master-slave.inc
2[connection master]
3DROP TABLE IF EXISTS t1;
4CREATE TABLE t1 (id INT(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)) ENGINE=InnoDB;
5INSERT INTO t1 VALUES ();
6SELECT COUNT(*) FROM t1;
7COUNT(*)
81
9include/rpl_restart_server.inc [server_number=2]
10include/start_slave.inc
11SELECT COUNT(*) FROM t1;
12COUNT(*)
131
14STOP SLAVE;
15include/wait_for_slave_to_stop.inc
16INSERT INTO t1 VALUES();
17SELECT COUNT(*) FROM t1;
18COUNT(*)
192
20SET GLOBAL debug="+d,crash_commit_before";
21START SLAVE;
22include/rpl_start_server.inc [server_number=2]
23include/start_slave.inc
24SELECT COUNT(*) FROM t1;
25COUNT(*)
262
27STOP SLAVE;
28include/wait_for_slave_to_stop.inc
29INSERT INTO t1 VALUES();
30SELECT COUNT(*) FROM t1;
31COUNT(*)
323
33SET GLOBAL debug="+d,crash_innodb_after_prepare";
34START SLAVE;
35include/rpl_start_server.inc [server_number=2]
36include/start_slave.inc
37SELECT COUNT(*) FROM t1;
38COUNT(*)
393
40STOP SLAVE;
41include/wait_for_slave_to_stop.inc
42INSERT INTO t1 VALUES();
43SELECT COUNT(*) FROM t1;
44COUNT(*)
454
46SET GLOBAL debug="+d,crash_innodb_before_commit";
47START SLAVE;
48include/rpl_start_server.inc [server_number=2]
49include/start_slave.inc
50SELECT COUNT(*) FROM t1;
51COUNT(*)
524
53DROP TABLE t1;
54include/rpl_end.inc
055
=== added file 'Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt'
--- Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl-slave.opt 2012-08-17 02:51:27 +0000
@@ -0,0 +1,1 @@
1--innodb-overwrite-relay-log-info=TRUE --skip-core-file --skip-stack-trace
02
=== added file 'Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test'
--- Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/rpl/t/rpl_percona_crash_resistant_rpl.test 2012-08-17 02:51:27 +0000
@@ -0,0 +1,117 @@
1# Tests for Percona crash-resistant replication feature
2--source include/have_innodb_plugin.inc
3--source include/master-slave.inc
4--source include/not_valgrind.inc
5--source include/not_crashrep.inc
6--source include/have_debug.inc
7
8#
9# Setup
10#
11
12--disable_query_log
13call mtr.add_suppression("InnoDB: Warning: innodb_overwrite_relay_log_info is enabled.");
14--enable_query_log
15
16connection master;
17
18--disable_warnings
19DROP TABLE IF EXISTS t1;
20--enable_warnings
21
22CREATE TABLE t1 (id INT(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)) ENGINE=InnoDB;
23
24#
25# Test the non-crashing case
26#
27
28INSERT INTO t1 VALUES ();
29SELECT COUNT(*) FROM t1;
30
31sync_slave_with_master;
32--let $rpl_server_number= 2
33--source include/rpl_restart_server.inc
34--source include/start_slave.inc
35SELECT COUNT(*) FROM t1;
36
37#
38# Test the crashing case where relay-log.info needs not to be overwritten
39#
40
41STOP SLAVE;
42--source include/wait_for_slave_to_stop.inc
43
44connection master;
45INSERT INTO t1 VALUES();
46SELECT COUNT(*) FROM t1;
47
48connection slave;
49SET GLOBAL debug="+d,crash_commit_before";
50--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
51--error 0,2013
52START SLAVE;
53--source include/wait_until_disconnected.inc
54--enable_reconnect
55
56--let $rpl_server_number= 2
57--source include/rpl_start_server.inc
58--source include/start_slave.inc
59connection master;
60sync_slave_with_master;
61SELECT COUNT(*) FROM t1;
62
63#
64# Test the rollback of slave position stored in the InnoDB trx header.
65#
66STOP SLAVE;
67--source include/wait_for_slave_to_stop.inc
68
69connection master;
70INSERT INTO t1 VALUES();
71SELECT COUNT(*) FROM t1;
72
73connection slave;
74SET GLOBAL debug="+d,crash_innodb_after_prepare";
75--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
76--error 0,2013
77START SLAVE;
78--source include/wait_until_disconnected.inc
79--enable_reconnect
80
81--let $rpl_server_number= 2
82--source include/rpl_start_server.inc
83--source include/start_slave.inc
84connection master;
85sync_slave_with_master;
86SELECT COUNT(*) FROM t1;
87
88#
89# Test crash with XA transaction recovery (bug 1012715)
90#
91STOP SLAVE;
92--source include/wait_for_slave_to_stop.inc
93connection master;
94INSERT INTO t1 VALUES();
95SELECT COUNT(*) FROM t1;
96
97connection slave;
98SET GLOBAL debug="+d,crash_innodb_before_commit";
99--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
100--error 0,2013
101START SLAVE;
102--source include/wait_until_disconnected.inc
103--enable_reconnect
104
105--let $rpl_server_number= 2
106--source include/rpl_start_server.inc
107--source include/start_slave.inc
108SELECT COUNT(*) FROM t1;
109
110#
111# Cleanup
112#
113
114connection master;
115DROP TABLE t1;
116
117--source include/rpl_end.inc
0118
=== modified file 'Percona-Server/storage/innodb_plugin/handler/ha_innodb.cc'
--- Percona-Server/storage/innodb_plugin/handler/ha_innodb.cc 2012-07-02 02:04:45 +0000
+++ Percona-Server/storage/innodb_plugin/handler/ha_innodb.cc 2012-08-17 02:51:27 +0000
@@ -2093,6 +2093,118 @@
2093 reset_template(prebuilt);2093 reset_template(prebuilt);
2094}2094}
20952095
2096/* The last read master log coordinates in the slave info file */
2097static char master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
2098static int master_log_pos;
2099/* The slave relay log coordinates in the slave info file after startup */
2100static char original_relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
2101static int original_relay_log_pos;
2102/* The master log coordinates in the slave info file after startup */
2103static char original_master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
2104static int original_master_log_pos;
2105
2106/*****************************************************************//**
2107Overwrites the MySQL relay log info file with the current master and relay log
2108coordinates from InnoDB. Skips overwrite if the master log position did not
2109change from the last overwrite. If the InnoDB master log position is equal
2110to position that was read from the info file on startup before any overwrites,
2111restores the original positions. */
2112static
2113void
2114innobase_do_overwrite_relay_log_info(void)
2115/*======================================*/
2116{
2117 char info_fname[FN_REFLEN];
2118 File info_fd = -1;
2119 int error = 0;
2120 char buff[FN_REFLEN*2+22*2+4];
2121 char *relay_info_log_pos;
2122 size_t buf_len;
2123
2124 if (master_log_fname[0] == '\0') {
2125 fprintf(stderr,
2126 "InnoDB: something wrong with relay-log.info. "
2127 "InnoDB will not overwrite it.\n");
2128 return;
2129 }
2130
2131 if (strcmp(master_log_fname, trx_sys_mysql_master_log_name) == 0
2132 && master_log_pos == trx_sys_mysql_master_log_pos) {
2133 fprintf(stderr,
2134 "InnoDB: InnoDB and relay-log.info are synchronized. "
2135 "InnoDB will not overwrite it.\n");
2136 return;
2137 }
2138
2139 /* If we overwrite the file back to the original master log position,
2140 restore the original relay log position too. This is required because
2141 we might have rolled back a prepared transaction and restored the
2142 original master log position from the InnoDB trx sys header, but the
2143 corresponding relay log position points to an already-purged file. */
2144 if (strcmp(original_master_log_fname, trx_sys_mysql_master_log_name)
2145 == 0
2146 && (original_master_log_pos == trx_sys_mysql_master_log_pos)) {
2147
2148 strncpy(trx_sys_mysql_relay_log_name, original_relay_log_fname,
2149 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
2150 trx_sys_mysql_relay_log_pos = original_relay_log_pos;
2151 }
2152
2153 fn_format(info_fname, relay_log_info_file, mysql_data_home, "",
2154 MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH);
2155
2156 if (access(info_fname, F_OK)) {
2157 /* File does not exist */
2158 error = 1;
2159 goto skip_overwrite;
2160 }
2161
2162 /* File exists */
2163 info_fd = my_open(info_fname, O_RDWR|O_BINARY, MYF(MY_WME));
2164 if (info_fd < 0) {
2165 error = 1;
2166 goto skip_overwrite;
2167 }
2168
2169 relay_info_log_pos = strmov(buff, trx_sys_mysql_relay_log_name);
2170 *relay_info_log_pos ++= '\n';
2171 relay_info_log_pos = longlong2str(trx_sys_mysql_relay_log_pos,
2172 relay_info_log_pos, 10);
2173 *relay_info_log_pos ++= '\n';
2174 relay_info_log_pos = strmov(relay_info_log_pos,
2175 trx_sys_mysql_master_log_name);
2176 *relay_info_log_pos ++= '\n';
2177 relay_info_log_pos = longlong2str(trx_sys_mysql_master_log_pos,
2178 relay_info_log_pos, 10);
2179 *relay_info_log_pos = '\n';
2180
2181 buf_len = (relay_info_log_pos - buff) + 1;
2182 if (my_write(info_fd, (uchar *)buff, buf_len, MY_WME) != buf_len) {
2183 error = 1;
2184 } else if (my_sync(info_fd, MY_WME)) {
2185 error = 1;
2186 }
2187
2188 if (info_fd >= 0) {
2189 my_close(info_fd, MYF(0));
2190 }
2191
2192 strncpy(master_log_fname, trx_sys_mysql_relay_log_name,
2193 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
2194 master_log_pos = trx_sys_mysql_master_log_pos;
2195
2196skip_overwrite:
2197 if (error) {
2198 fprintf(stderr,
2199 "InnoDB: ERROR: error occured during overwriting "
2200 "relay-log.info.\n");
2201 } else {
2202 fprintf(stderr,
2203 "InnoDB: relay-log.info was overwritten.\n");
2204 }
2205}
2206
2207
2096/*********************************************************************//**2208/*********************************************************************//**
2097Opens an InnoDB database.2209Opens an InnoDB database.
2098@return 0 on success, error code on failure */2210@return 0 on success, error code on failure */
@@ -2221,12 +2333,13 @@
2221#ifdef HAVE_REPLICATION2333#ifdef HAVE_REPLICATION
2222#ifdef MYSQL_SERVER2334#ifdef MYSQL_SERVER
2223 /* read master log position from relay-log.info if exists */2335 /* read master log position from relay-log.info if exists */
2224 char fname[FN_REFLEN+128];2336 char info_fname[FN_REFLEN];
2225 int pos;2337 char relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
2338 int relay_log_pos;
2226 int info_fd;2339 int info_fd;
2227 IO_CACHE info_file;2340 IO_CACHE info_file;
22282341
2229 fname[0] = '\0';2342 info_fname[0] = '\0';
22302343
2231 if(innobase_overwrite_relay_log_info) {2344 if(innobase_overwrite_relay_log_info) {
22322345
@@ -2235,13 +2348,14 @@
2235 " Updates in other storage engines may have problem with consistency.\n");2348 " Updates in other storage engines may have problem with consistency.\n");
22362349
2237 bzero((char*) &info_file, sizeof(info_file));2350 bzero((char*) &info_file, sizeof(info_file));
2238 fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);2351 fn_format(info_fname, relay_log_info_file, mysql_data_home, "", 4+32);
22392352
2240 int error=0;2353 int error=0;
22412354
2242 if (!access(fname,F_OK)) {2355 if (!access(info_fname,F_OK)) {
2243 /* exist */2356 /* exist */
2244 if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {2357 if ((info_fd = my_open(info_fname, O_RDWR | O_BINARY,
2358 MYF(MY_WME))) < 0) {
2245 error=1;2359 error=1;
2246 } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,2360 } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
2247 READ_CACHE, 0L, 0, MYF(MY_WME))) {2361 READ_CACHE, 0L, 0, MYF(MY_WME))) {
@@ -2252,16 +2366,18 @@
2252relay_info_error:2366relay_info_error:
2253 if (info_fd >= 0)2367 if (info_fd >= 0)
2254 my_close(info_fd, MYF(0));2368 my_close(info_fd, MYF(0));
2255 fname[0] = '\0';2369 master_log_fname[0] = '\0';
2256 goto skip_relay;2370 goto skip_relay;
2257 }2371 }
2258 } else {2372 } else {
2259 fname[0] = '\0';2373 master_log_fname[0] = '\0';
2260 goto skip_relay;2374 goto skip_relay;
2261 }2375 }
22622376
2263 if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */2377 if (init_strvar_from_file(relay_log_fname, sizeof(relay_log_fname),
2264 init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) { 2378 &info_file, "")
2379 || /* dummy (it is relay-log) */ init_intvar_from_file(
2380 &relay_log_pos, &info_file, BIN_LOG_HEADER_SIZE)) {
2265 end_io_cache(&info_file);2381 end_io_cache(&info_file);
2266 error=1;2382 error=1;
2267 goto relay_info_error;2383 goto relay_info_error;
@@ -2270,13 +2386,19 @@
2270 fprintf(stderr,2386 fprintf(stderr,
2271 "InnoDB: relay-log.info is detected.\n"2387 "InnoDB: relay-log.info is detected.\n"
2272 "InnoDB: relay log: position %u, file name %s\n",2388 "InnoDB: relay log: position %u, file name %s\n",
2273 pos, fname);2389 relay_log_pos, relay_log_fname);
22742390
2275 strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);2391 strncpy(trx_sys_mysql_relay_log_name, relay_log_fname,
2276 trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;2392 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
22772393 trx_sys_mysql_relay_log_pos = (ib_int64_t) relay_log_pos;
2278 if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||2394
2279 init_intvar_from_file(&pos, &info_file, 0)) {2395 strncpy(original_relay_log_fname, relay_log_fname,
2396 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
2397 original_relay_log_pos = relay_log_pos;
2398
2399 if (init_strvar_from_file(master_log_fname, sizeof(master_log_fname),
2400 &info_file, "")
2401 || init_intvar_from_file(&master_log_pos, &info_file, 0)) {
2280 end_io_cache(&info_file);2402 end_io_cache(&info_file);
2281 error=1;2403 error=1;
2282 goto relay_info_error;2404 goto relay_info_error;
@@ -2284,10 +2406,15 @@
22842406
2285 fprintf(stderr,2407 fprintf(stderr,
2286 "InnoDB: master log: position %u, file name %s\n",2408 "InnoDB: master log: position %u, file name %s\n",
2287 pos, fname);2409 master_log_pos, master_log_fname);
22882410
2289 strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);2411 strncpy(trx_sys_mysql_master_log_name, master_log_fname,
2290 trx_sys_mysql_master_log_pos = (ib_int64_t) pos;2412 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
2413 trx_sys_mysql_master_log_pos = (ib_int64_t) master_log_pos;
2414
2415 strncpy(original_master_log_fname, master_log_fname,
2416 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
2417 original_master_log_pos = master_log_pos;
22912418
2292 end_io_cache(&info_file);2419 end_io_cache(&info_file);
2293 if (info_fd >= 0)2420 if (info_fd >= 0)
@@ -2587,75 +2714,9 @@
2587 goto mem_free_and_error;2714 goto mem_free_and_error;
2588 }2715 }
25892716
2590#ifdef HAVE_REPLICATION
2591#ifdef MYSQL_SERVER
2592 if(innobase_overwrite_relay_log_info) {2717 if(innobase_overwrite_relay_log_info) {
2593 /* If InnoDB progressed from relay-log.info, overwrite it */2718 innobase_do_overwrite_relay_log_info();
2594 if (fname[0] == '\0') {2719 }
2595 fprintf(stderr,
2596 "InnoDB: something wrong with relay-info.log. InnoDB will not overwrite it.\n");
2597 } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
2598 || pos != trx_sys_mysql_master_log_pos) {
2599 /* Overwrite relay-log.info */
2600 bzero((char*) &info_file, sizeof(info_file));
2601 fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
2602
2603 int error = 0;
2604
2605 if (!access(fname,F_OK)) {
2606 /* exist */
2607 if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
2608 error = 1;
2609 } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
2610 WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
2611 error = 1;
2612 }
2613
2614 if (error) {
2615 if (info_fd >= 0)
2616 my_close(info_fd, MYF(0));
2617 goto skip_overwrite;
2618 }
2619 } else {
2620 error = 1;
2621 goto skip_overwrite;
2622 }
2623
2624 char buff[FN_REFLEN*2+22*2+4], *pos;
2625
2626 my_b_seek(&info_file, 0L);
2627 pos=strmov(buff, trx_sys_mysql_relay_log_name);
2628 *pos++='\n';
2629 pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
2630 *pos++='\n';
2631 pos=strmov(pos, trx_sys_mysql_master_log_name);
2632 *pos++='\n';
2633 pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
2634 *pos='\n';
2635
2636 if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
2637 error = 1;
2638 if (flush_io_cache(&info_file))
2639 error = 1;
2640
2641 end_io_cache(&info_file);
2642 if (info_fd >= 0)
2643 my_close(info_fd, MYF(0));
2644skip_overwrite:
2645 if (error) {
2646 fprintf(stderr,
2647 "InnoDB: ERROR: error occured during overwriting relay-log.info.\n");
2648 } else {
2649 fprintf(stderr,
2650 "InnoDB: relay-log.info was overwritten.\n");
2651 }
2652 } else {
2653 fprintf(stderr,
2654 "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
2655 }
2656 }
2657#endif /* MYSQL_SERVER */
2658#endif /* HAVE_REPLICATION */
26592720
2660 innobase_open_tables = hash_create(200);2721 innobase_open_tables = hash_create(200);
2661 pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);2722 pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
@@ -2757,38 +2818,50 @@
2757 | HA_ONLINE_ADD_PK_INDEX_NO_WRITES);2818 | HA_ONLINE_ADD_PK_INDEX_NO_WRITES);
2758}2819}
27592820
2760/*****************************************************************//**2821/****************************************************************//**
2761Commits a transaction in an InnoDB database. */2822Copy the current replication position from MySQL to a transaction. */
2762static2823static
2763void2824void
2764innobase_commit_low(2825innobase_copy_repl_coords_to_trx(
2765/*================*/2826/*=============================*/
2766 trx_t* trx) /*!< in: transaction handle */2827 const THD* thd, /*!< in: thread handle */
2828 trx_t* trx) /*!< in/out: transaction */
2767{2829{
2768 if (trx->conc_state == TRX_NOT_STARTED) {
2769
2770 return;
2771 }
2772
2773#ifdef HAVE_REPLICATION
2774#ifdef MYSQL_SERVER
2775 THD *thd=current_thd;
2776
2777 if (thd && thd->slave_thread) {2830 if (thd && thd->slave_thread) {
2778 /* Update the replication position info inside InnoDB */2831 const Relay_log_info* rli = &active_mi->rli;
2832
2779 trx->mysql_master_log_file_name2833 trx->mysql_master_log_file_name
2780 = active_mi->rli.group_master_log_name;2834 = rli->group_master_log_name;
2781 trx->mysql_master_log_pos2835 trx->mysql_master_log_pos
2782 = ((ib_int64_t)active_mi->rli.group_master_log_pos +2836 = ((ib_int64_t)rli->group_master_log_pos
2783 ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -2837 + ((ib_int64_t)
2784 (ib_int64_t)active_mi->rli.group_relay_log_pos));2838 rli->future_event_relay_log_pos
2839 - (ib_int64_t)rli->group_relay_log_pos));
2785 trx->mysql_relay_log_file_name2840 trx->mysql_relay_log_file_name
2786 = active_mi->rli.group_relay_log_name;2841 = rli->group_relay_log_name;
2787 trx->mysql_relay_log_pos2842 trx->mysql_relay_log_pos
2788 = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;2843 = (ib_int64_t)rli->future_event_relay_log_pos;
2789 }2844 }
2790#endif /* MYSQL_SERVER */2845}
2791#endif /* HAVE_REPLICATION */2846
2847/*****************************************************************//**
2848Commits a transaction in an InnoDB database. */
2849static
2850void
2851innobase_commit_low(
2852/*================*/
2853 trx_t* trx) /*!< in: transaction handle */
2854{
2855 if (trx->conc_state == TRX_NOT_STARTED) {
2856
2857 return;
2858 }
2859
2860 /* Save the current replication position for write to trx sys header
2861 for undo purposes, see the comment at corresponding call at
2862 innobase_xa_prepare(). */
2863
2864 innobase_copy_repl_coords_to_trx(current_thd, trx);
27922865
2793 trx_commit_for_mysql(trx);2866 trx_commit_for_mysql(trx);
2794}2867}
@@ -2898,6 +2971,9 @@
2898 if (all2971 if (all
2899 || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {2972 || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
29002973
2974 DBUG_EXECUTE_IF("crash_innodb_before_commit",
2975 DBUG_SUICIDE(););
2976
2901 /* We were instructed to commit the whole transaction, or2977 /* We were instructed to commit the whole transaction, or
2902 this is an SQL statement end and autocommit is on */2978 this is an SQL statement end and autocommit is on */
29032979
@@ -10657,7 +10733,27 @@
1065710733
10658 ut_ad(trx->active_trans);10734 ut_ad(trx->active_trans);
1065910735
10736 /* Update the replication position info in current trx. This
10737 is different from the binlog position update that happens
10738 during XA COMMIT. In contrast to that, the slave position is
10739 an actual part of the changes made by this transaction and thus
10740 must be updated in the XA PREPARE stage. Since the trx sys
10741 header page changes are not undo-logged, again store this
10742 position in a different field in the XA COMMIT stage, so that
10743 it might be used in case of rollbacks. */
10744
10745 /* Since currently there might be only one slave SQL thread, we
10746 don't need to take any precautions (e.g. prepare_commit_mutex)
10747 to ensure position ordering. Revisit this in 5.6 which has
10748 both the multi-threaded replication to cause us problems and
10749 the group commit to solve them. */
10750
10751 innobase_copy_repl_coords_to_trx(thd, trx);
10752
10660 error = (int) trx_prepare_for_mysql(trx);10753 error = (int) trx_prepare_for_mysql(trx);
10754
10755 DBUG_EXECUTE_IF("crash_innodb_after_prepare",
10756 DBUG_SUICIDE(););
10661 } else {10757 } else {
10662 /* We just mark the SQL statement ended and do not do a10758 /* We just mark the SQL statement ended and do not do a
10663 transaction prepare */10759 transaction prepare */
@@ -10780,6 +10876,22 @@
10780 if (trx) {10876 if (trx) {
10781 int ret = innobase_rollback_trx(trx);10877 int ret = innobase_rollback_trx(trx);
10782 trx_free_for_background(trx);10878 trx_free_for_background(trx);
10879
10880 if (innobase_overwrite_relay_log_info) {
10881
10882 /* On rollback of a prepared transaction revert the
10883 current slave positions to the ones recorded by the
10884 last COMMITTed transaction. This has an effect of
10885 undoing the position change caused by the transaction
10886 being rolled back. Assumes single-threaded slave SQL
10887 thread. If the server has non-master write traffic
10888 with XA rollbacks, this will cause additional spurious
10889 slave info log overwrites, which should be harmless. */
10890
10891 trx_sys_print_committed_mysql_master_log_pos();
10892 innobase_do_overwrite_relay_log_info();
10893 }
10894
10783 return(ret);10895 return(ret);
10784 } else {10896 } else {
10785 return(XAER_NOTA);10897 return(XAER_NOTA);
1078610898
=== modified file 'Percona-Server/storage/innodb_plugin/include/trx0sys.h'
--- Percona-Server/storage/innodb_plugin/include/trx0sys.h 2012-04-02 02:09:15 +0000
+++ Percona-Server/storage/innodb_plugin/include/trx0sys.h 2012-08-17 02:51:27 +0000
@@ -357,6 +357,14 @@
357trx_sys_print_mysql_binlog_offset(void);357trx_sys_print_mysql_binlog_offset(void);
358/*===================================*/358/*===================================*/
359/*****************************************************************//**359/*****************************************************************//**
360Prints to stderr the MySQL master log offset info in the trx system header
361COMMIT set of fields if the magic number shows it valid and stores it
362in global variables. */
363UNIV_INTERN
364void
365trx_sys_print_committed_mysql_master_log_pos(void);
366/*==============================================*/
367/*****************************************************************//**
360Prints to stderr the MySQL master log offset info in the trx system header if368Prints to stderr the MySQL master log offset info in the trx system header if
361the magic number shows it valid. */369the magic number shows it valid. */
362UNIV_INTERN370UNIV_INTERN
@@ -536,10 +544,16 @@
536//# error "UNIV_PAGE_SIZE < 4096"544//# error "UNIV_PAGE_SIZE < 4096"
537//#endif545//#endif
538/** The offset of the MySQL replication info in the trx system header;546/** The offset of the MySQL replication info in the trx system header;
539this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */547this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below. These are
548written at prepare time and are the main copy. */
540#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)549#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
541#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)550#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
542551
552/** The copy of the above which is made at transaction COMMIT time. If binlog
553crash recovery rollbacks a PREPAREd transaction, they are copied back. */
554#define TRX_SYS_COMMIT_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 3000)
555#define TRX_SYS_COMMIT_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 2500)
556
543/** The offset of the MySQL binlog offset info in the trx system header */557/** The offset of the MySQL binlog offset info in the trx system header */
544#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)558#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
545#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /*!< magic number which is559#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /*!< magic number which is
546560
=== modified file 'Percona-Server/storage/innodb_plugin/trx/trx0sys.c'
--- Percona-Server/storage/innodb_plugin/trx/trx0sys.c 2012-04-02 02:09:15 +0000
+++ Percona-Server/storage/innodb_plugin/trx/trx0sys.c 2012-08-17 02:51:27 +0000
@@ -947,8 +947,31 @@
947}947}
948948
949/*****************************************************************//**949/*****************************************************************//**
950Prints to stderr the MySQL master log offset info in the trx system header if950Reads the log coordinates at the given offset in the trx sys header. */
951the magic number shows it valid. */951static
952void
953trx_sys_read_log_pos(
954/*=================*/
955 const trx_sysf_t* sys_header, /*!< in: the trx sys header */
956 uint header_offset, /*!< in: coord offset in the
957 header */
958 char* log_fn, /*!< out: the log file name */
959 ib_int64_t* log_pos) /*!< out: the log poistion */
960{
961 ut_memcpy(log_fn, sys_header + header_offset + TRX_SYS_MYSQL_LOG_NAME,
962 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
963
964 *log_pos =
965 (((ib_int64_t)mach_read_from_4(sys_header + header_offset
966 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
967 + mach_read_from_4(sys_header + header_offset
968 + TRX_SYS_MYSQL_LOG_OFFSET_LOW);
969}
970
971/*****************************************************************//**
972Prints to stderr the MySQL master log offset info in the trx system header
973PREPARE set of fields if the magic number shows it valid and stores it
974in global variables. */
952UNIV_INTERN975UNIV_INTERN
953void976void
954trx_sys_print_mysql_master_log_pos(void)977trx_sys_print_mysql_master_log_pos(void)
@@ -970,60 +993,79 @@
970 return;993 return;
971 }994 }
972995
973 fprintf(stderr,
974 "InnoDB: In a MySQL replication slave the last"
975 " master binlog file\n"
976 "InnoDB: position %lu %lu, file name %s\n",
977 (ulong) mach_read_from_4(sys_header
978 + TRX_SYS_MYSQL_MASTER_LOG_INFO
979 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
980 (ulong) mach_read_from_4(sys_header
981 + TRX_SYS_MYSQL_MASTER_LOG_INFO
982 + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
983 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
984 + TRX_SYS_MYSQL_LOG_NAME);
985
986 fprintf(stderr,
987 "InnoDB: and relay log file\n"
988 "InnoDB: position %lu %lu, file name %s\n",
989 (ulong) mach_read_from_4(sys_header
990 + TRX_SYS_MYSQL_RELAY_LOG_INFO
991 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
992 (ulong) mach_read_from_4(sys_header
993 + TRX_SYS_MYSQL_RELAY_LOG_INFO
994 + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
995 sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
996 + TRX_SYS_MYSQL_LOG_NAME);
997
998 /* Copy the master log position info to global variables we can996 /* Copy the master log position info to global variables we can
999 use in ha_innobase.cc to initialize glob_mi to right values */997 use in ha_innobase.cc to initialize glob_mi to right values */
1000998 trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_MASTER_LOG_INFO,
1001 ut_memcpy(trx_sys_mysql_master_log_name,999 trx_sys_mysql_master_log_name,
1002 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO1000 &trx_sys_mysql_master_log_pos);
1003 + TRX_SYS_MYSQL_LOG_NAME,1001
1004 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);1002 trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_RELAY_LOG_INFO,
10051003 trx_sys_mysql_relay_log_name,
1006 trx_sys_mysql_master_log_pos1004 &trx_sys_mysql_relay_log_pos);
1007 = (((ib_int64_t) mach_read_from_4(1005
1008 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO1006 mtr_commit(&mtr);
1009 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)1007
1010 + ((ib_int64_t) mach_read_from_4(1008 fprintf(stderr,
1011 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO1009 "InnoDB: In a MySQL replication slave the last"
1012 + TRX_SYS_MYSQL_LOG_OFFSET_LOW));1010 " master binlog file\n"
10131011 "InnoDB: position %llu, file name %s\n",
1014 ut_memcpy(trx_sys_mysql_relay_log_name,1012 trx_sys_mysql_master_log_pos,
1015 sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO1013 trx_sys_mysql_master_log_name);
1016 + TRX_SYS_MYSQL_LOG_NAME,1014
1017 TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);1015 fprintf(stderr,
10181016 "InnoDB: and relay log file\n"
1019 trx_sys_mysql_relay_log_pos1017 "InnoDB: position %llu, file name %s\n",
1020 = (((ib_int64_t) mach_read_from_4(1018 trx_sys_mysql_relay_log_pos,
1021 sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO1019 trx_sys_mysql_relay_log_name);
1022 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)1020}
1023 + ((ib_int64_t) mach_read_from_4(1021
1024 sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO1022/*****************************************************************//**
1025 + TRX_SYS_MYSQL_LOG_OFFSET_LOW));1023Prints to stderr the MySQL master log offset info in the trx system header
1026 mtr_commit(&mtr);1024COMMIT set of fields if the magic number shows it valid and stores it
1025in global variables. */
1026UNIV_INTERN
1027void
1028trx_sys_print_committed_mysql_master_log_pos(void)
1029/*==============================================*/
1030{
1031 trx_sysf_t* sys_header;
1032 mtr_t mtr;
1033
1034 mtr_start(&mtr);
1035
1036 sys_header = trx_sysf_get(&mtr);
1037
1038 if (mach_read_from_4(sys_header + TRX_SYS_COMMIT_MASTER_LOG_INFO
1039 + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
1040 != TRX_SYS_MYSQL_LOG_MAGIC_N) {
1041
1042 mtr_commit(&mtr);
1043
1044 return;
1045 }
1046
1047 /* Copy the master log position info to global variables we can
1048 use in ha_innobase.cc to initialize glob_mi to right values */
1049 trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_MASTER_LOG_INFO,
1050 trx_sys_mysql_master_log_name,
1051 &trx_sys_mysql_master_log_pos);
1052
1053 trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_RELAY_LOG_INFO,
1054 trx_sys_mysql_relay_log_name,
1055 &trx_sys_mysql_relay_log_pos);
1056
1057 mtr_commit(&mtr);
1058
1059 fprintf(stderr,
1060 "InnoDB: In a MySQL replication slave the last"
1061 " master binlog file\n"
1062 "InnoDB: position %llu, file name %s\n",
1063 trx_sys_mysql_master_log_pos, trx_sys_mysql_master_log_name);
1064
1065 fprintf(stderr,
1066 "InnoDB: and relay log file\n"
1067 "InnoDB: position %llu, file name %s\n",
1068 trx_sys_mysql_relay_log_pos, trx_sys_mysql_relay_log_name);
1027}1069}
10281070
1029/****************************************************************//**1071/****************************************************************//**
10301072
=== modified file 'Percona-Server/storage/innodb_plugin/trx/trx0trx.c'
--- Percona-Server/storage/innodb_plugin/trx/trx0trx.c 2012-04-02 02:09:15 +0000
+++ Percona-Server/storage/innodb_plugin/trx/trx0trx.c 2012-08-17 02:51:27 +0000
@@ -904,12 +904,12 @@
904 sys_header,904 sys_header,
905 trx->mysql_relay_log_file_name,905 trx->mysql_relay_log_file_name,
906 trx->mysql_relay_log_pos,906 trx->mysql_relay_log_pos,
907 TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);907 TRX_SYS_COMMIT_RELAY_LOG_INFO, &mtr);
908 trx_sys_update_mysql_binlog_offset(908 trx_sys_update_mysql_binlog_offset(
909 sys_header,909 sys_header,
910 trx->mysql_master_log_file_name,910 trx->mysql_master_log_file_name,
911 trx->mysql_master_log_pos,911 trx->mysql_master_log_pos,
912 TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);912 TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr);
913 trx->mysql_master_log_file_name = "";913 trx->mysql_master_log_file_name = "";
914 }914 }
915915
@@ -2002,6 +2002,23 @@
20022002
2003 mutex_exit(&(rseg->mutex));2003 mutex_exit(&(rseg->mutex));
20042004
2005 if (trx->mysql_master_log_file_name[0] != '\0') {
2006 /* This database server is a MySQL replication slave */
2007 trx_sysf_t* sys_header = trx_sysf_get(&mtr);
2008
2009 trx_sys_update_mysql_binlog_offset(
2010 sys_header,
2011 trx->mysql_relay_log_file_name,
2012 trx->mysql_relay_log_pos,
2013 TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
2014 trx_sys_update_mysql_binlog_offset(
2015 sys_header,
2016 trx->mysql_master_log_file_name,
2017 trx->mysql_master_log_pos,
2018 TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
2019 trx->mysql_master_log_file_name = "";
2020 }
2021
2005 /*--------------*/2022 /*--------------*/
2006 mtr_commit(&mtr); /* This mtr commit makes the2023 mtr_commit(&mtr); /* This mtr commit makes the
2007 transaction prepared in the file-based2024 transaction prepared in the file-based

Subscribers

People subscribed via source and target branches