Merge lp:~vlad-lesin/percona-xtrabackup/2.1-apply-archived-logs-innodb5.6 into lp:percona-xtrabackup/2.1

Proposed by Vlad Lesin
Status: Merged
Approved by: Alexey Kopytov
Approved revision: no longer in the source branch.
Merged at revision: 675
Proposed branch: lp:~vlad-lesin/percona-xtrabackup/2.1-apply-archived-logs-innodb5.6
Merge into: lp:percona-xtrabackup/2.1
Diff against target: 1525 lines (+1383/-17)
3 files modified
patches/innodb56.patch (+822/-0)
src/xtrabackup.cc (+172/-17)
test/t/xb_apply_archived_logs.sh (+389/-0)
To merge this branch: bzr merge lp:~vlad-lesin/percona-xtrabackup/2.1-apply-archived-logs-innodb5.6
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
Laurynas Biveinis (community) Needs Fixing
Review via email: mp+160804@code.launchpad.net

Description of the change

This is implementation of ability to apply archived logs in xtrabackup which is described here: https://blueprints.launchpad.net/percona-xtrabackup/+spec/log-archiving-restore
See commit comment for more detailed description.

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

A merge conflict, unless spurious, that needs rebasing on the current trunk?

review: Needs Fixing
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> A merge conflict, unless spurious, that needs rebasing on the current trunk?
I have just rebased it on the current trunk.

Revision history for this message
Alexey Kopytov (akopytov) wrote :
Download full text (3.2 KiB)

Vlad,

    - I don't think the XtraBackup part should pull the entire server
      implementation of log archiving. It looks like only a minor part
      of it should be applied to InnoDB 5.6 code base to be able to
      parse and apply archived logs? As in, do we really need
      fil_space_contains_node(), log_sys->archive_buf initialization,
      changes to log_checkpoint_set_nth_group_info(), etc.?

    - can you clarify the following change? I.e. under what
      circumstances exactly can a tablespace exist when we are trying
      to replay MLOG_FILE_CREATE from the archived logs?

+@@ -3325,9 +3341,13 @@
+ path = fil_make_ibd_name(tablename, false);
+ }
+
++ /* The files can already exist in the case of archived logs applying */
+ file = os_file_create(
+ innodb_file_data_key, path,
+- OS_FILE_CREATE | OS_FILE_ON_ERROR_NO_EXIT,
++ (srv_archive_recovery ?
++ OS_FILE_OVERWRITE :
++ OS_FILE_CREATE) |
++ OS_FILE_ON_ERROR_NO_EXIT,
+ OS_FILE_NORMAL,
+ OS_DATA_FILE,
+ &ret);

    - s/alligned to the up of log file block/aligned up to the log block size/

    - please clarify why the following change is needed. As I
      understand, we don't start the FTS optimize thread in
      XtraBackup. That code is also missing block braces and is using
      spaces instead of tabs for indentation:

+@@ -3032,7 +3032,8 @@
+
+ ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
+
+- os_event_set(exit_event);
++ if (exit_event)
++ os_event_set(exit_event);
+
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
+

    - please use LSN_PF instead of "%llu"

    - in recv_recovery_from_archive_start() we ignore the first_log_no
      argument and use xtrabackup_arch_first_file_lsn instead. wouldn't
      it be better to pass xtrabackup_arch_first_file_lsn as the
      first_log_no argument to recv_recovery_from_archive_start() and
      get rid of min/max_arch_log_no in
      innobase_start_or_create_for_mysql()?

    - in xb_data_files_init() the patch replaces min/max_flushed_lsn
      declarations with min/max_arch_log_no. Which are not really
      used. but then the call still calls open_or_create_data_files()
      with the (now non-existing) flushed_lsn variables?

    - s/xtrabackup: Note: opening archived log directory %s was
      failed/xtrabackup: error: cannot open archived log directory %s/

    - replace the strstr() call in xtrabackup_arch_search_files() with
      strncmp()

    - xtrabackup_arch_search_files() is declared to return bool, but
      returns xtrabackup_arch_first_file_lsn?

    - we tend to use the InnoDB code style in xtrabackup.cc. In
      particular, the opening brace must be on the same line as the
      'if' statement. And braces should be used even for
      single-statement 'if' blocks;

    - s/trunsactions/transactions/

    - s/undid/rolled back/

    - the check for Percona Server 5.6 doesn't work (try starting it
      with an upstream 5.6 server). The reason is that the syntax for
      string equality comparison is "val1 = val2", not "val1=val2"

    - the test case doesn't wo...

Read more...

review: Needs Fixing
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Vlad,

Why don't we use --log-arch-dir option (with same name as server one) instead of --archived-logs-dir?

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

On 05/06/2013 06:21 PM, Sergei Glushchenko wrote:
> Vlad,
>
> Why don't we use --log-arch-dir option (with same name as server one) instead of --archived-logs-dir?
>

This is good idea, thanks.

--
Vlad Lesin, Software Engineer, Percona Inc.
<email address hidden>
skype: vlad_lesin
JID: <email address hidden>
ICQ: 204036003
phone: +79051122311
Tula, Russia (GMT +4)

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :
Download full text (6.8 KiB)

On 05/01/2013 02:40 PM, Alexey Kopytov wrote:
> - I don't think the XtraBackup part should pull the entire server
> implementation of log archiving. It looks like only a minor part
> of it should be applied to InnoDB 5.6 code base to be able to
> parse and apply archived logs? As in, do we really need
> fil_space_contains_node(), log_sys->archive_buf initialization,
> changes to log_checkpoint_set_nth_group_info(), etc.?

Done.

> - can you clarify the following change? I.e. under what
> circumstances exactly can a tablespace exist when we are trying
> to replay MLOG_FILE_CREATE from the archived logs?

Yes. It can be for example in the case when this file did not exist at
the beginning of backup process and was created somewhere in the middle
of backup process. So log file contains "create" command as backup
process started tracking it before the file creation, but data directory
contains this file as it was copied from original directory. I copied
this explanation to code comment.

> +@@ -3325,9 +3341,13 @@
> + path = fil_make_ibd_name(tablename, false);
> + }
> +
> ++ /* The files can already exist in the case of archived logs applying */
> + file = os_file_create(
> + innodb_file_data_key, path,
> +- OS_FILE_CREATE | OS_FILE_ON_ERROR_NO_EXIT,
> ++ (srv_archive_recovery ?
> ++ OS_FILE_OVERWRITE :
> ++ OS_FILE_CREATE) |
> ++ OS_FILE_ON_ERROR_NO_EXIT,
> + OS_FILE_NORMAL,
> + OS_DATA_FILE,
> + &ret);
>
> - s/alligned to the up of log file block/aligned up to the log block size/

Done.

> - please clarify why the following change is needed. As I
> understand, we don't start the FTS optimize thread in
> XtraBackup. That code is also missing block braces and is using
> spaces instead of tabs for indentation:
>
> +@@ -3032,7 +3032,8 @@
> +
> + ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
> +
> +- os_event_set(exit_event);
> ++ if (exit_event)
> ++ os_event_set(exit_event);
> +
> + /* We count the number of threads in os_thread_exit(). A created
> + thread should always use that to exit and not use return() to exit. */
> +

I fixed using spaces instead tabs for indentation and missing braces.

As I understuud FTS optimize thread is started in xtrabackup because I
have the following backtrace in the case of missing exit_event condition:
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff633f037 in __GI_raise (sig=sig@entry=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007ffff6342698 in __GI_abort () at abort.c:90
#2 0x000000000063ac80 in os_event_set (event=0x0)
     at
/home/vlesin/src/work/percona-xtrabackup-2.1-arch-log/mysql-5.6/storage/innobase/os/os0sync.cc:437
#3 0x00000000006063ec in fts_optimize_thread (arg=0x1e604e8)
     at
/home/vlesin/src/work/percona-xtrabackup-2.1-arch-log/mysql-5.6/storage/innobase/fts/fts0opt.cc:3036
#4 0x00007ffff79bcf8e in start_thread (arg=0x7fffd57fa700) at
pthread_create.c:311
#5 0x00007ffff6401e1d in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:113

Here is the backtrace of FTS initializati...

Read more...

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

On 05/06/2013 06:21 PM, Sergei Glushchenko wrote:
> Vlad,
>
> Why don't we use --log-arch-dir option (with same name as server one) instead of --archived-logs-dir?
>

Done.

--
Vlad Lesin, Software Engineer, Percona Inc.
<email address hidden>
skype: vlad_lesin
JID: <email address hidden>
ICQ: 204036003
phone: +79051122311
Tula, Russia (GMT +4)

Revision history for this message
Alexey Kopytov (akopytov) wrote :
Download full text (6.3 KiB)

Hi Vlad,

General comments:

     - I think this MP should wait until 5.6.11-60.3 with the fix for bug
       #1172591 is released. Then the test suite should use 5.6.11-60.30
       for testing instead of the custom build

     - there should be a separate fix for bug #1177182 for both 2.0 and
2.1, and again, this branch should be rebased once the fix is merged to
trunks.

     - xtrabackup_arch_search_files() should use msg() instead of
       fprintf(stderr,...)

Other comments/questions:

On Fri, 10 May 2013 09:42:06 +0400, Vlad Lesin wrote:
>> - can you clarify the following change? I.e. under what
>> circumstances exactly can a tablespace exist when we are trying
>> to replay MLOG_FILE_CREATE from the archived logs?
>
> Yes. It can be for example in the case when this file did not exist at
> the beginning of backup process and was created somewhere in the middle
> of backup process. So log file contains "create" command as backup
> process started tracking it before the file creation, but data directory
> contains this file as it was copied from original directory. I copied
> this explanation to code comment.
>

If a tablespace exists on recovery, it is created into fil_system before
the recovery starts. When replaying MLOG_FILE_CREATE,
fil_op_log_parse_or_replay first checks if the tablespace exists in
fil_system and does nothing. So I still don't understand that change in
fil_create_new_single_table_tablespace().

>
>> +@@ -3325,9 +3341,13 @@
>> + path = fil_make_ibd_name(tablename, false);
>> + }
>> +
>> ++ /* The files can already exist in the case of archived logs
>> applying */
>> + file = os_file_create(
>> + innodb_file_data_key, path,
>> +- OS_FILE_CREATE | OS_FILE_ON_ERROR_NO_EXIT,
>> ++ (srv_archive_recovery ?
>> ++ OS_FILE_OVERWRITE :
>> ++ OS_FILE_CREATE) |
>> ++ OS_FILE_ON_ERROR_NO_EXIT,
>> + OS_FILE_NORMAL,
>> + OS_DATA_FILE,
>> + &ret);
>>
>> - s/alligned to the up of log file block/aligned up to the log
>> block size/
>
> Done.
>

Not fully done, it is "aligned" (single "l"), not "alligned".

>> - please clarify why the following change is needed. As I
>> understand, we don't start the FTS optimize thread in
>> XtraBackup. That code is also missing block braces and is using
>> spaces instead of tabs for indentation:
>>
>> +@@ -3032,7 +3032,8 @@
>> +
>> + ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
>> +
>> +- os_event_set(exit_event);
>> ++ if (exit_event)
>> ++ os_event_set(exit_event);
>> +
>> + /* We count the number of threads in os_thread_exit(). A created
>> + thread should always use that to exit and not use return() to
>> exit. */
>> +
>
> I fixed using spaces instead tabs for indentation and missing braces.
>
> As I understuud FTS optimize thread is started in xtrabackup because I
>

OK, I see the problem now, reported as bug #1179193. This means we have
to fix that bug separately in both 2.0 and 2.1, and then rebase this
branch on 2.1 trunk with that fix included.

>> - please use LSN_PF instead of "%llu"
>
...

Read more...

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

On 05/12/2013 04:48 PM, Alexey Kopytov wrote:
>>> - in recv_recovery_from_archive_start() we ignore the first_log_no
>>> argument and use xtrabackup_arch_first_file_lsn instead. wouldn't
>>> it be better to pass xtrabackup_arch_first_file_lsn as the
>>> first_log_no argument to recv_recovery_from_archive_start() and

As I understood our chat right the main cause of this change is to
remove 'fake' arguments from recv_recovery_from_archive_start().

Why just don't remove first_log_no from
recv_recovery_from_archive_start() arguments list? I don't see any
benefits in passing xtrabackup_arch_first_file_lsn and
xtrabackup_arch_last_file_lsn to recv_recovery_from_archive_start() as
arguments because in this case we just remove using global external
variables from recv_recovery_from_archive_start() to
innobase_start_or_create_for_mysql().

 >>> get rid of min/max_arch_log_no in
 >>> innobase_start_or_create_for_mysql()?

Right. In this case we could remove min/max_arch_log_no from
open_or_create_data_files() arguments list and from xb_data_files_init()
too.

--
Vlad Lesin, Software Engineer, Percona Inc.
<email address hidden>
skype: vlad_lesin
JID: <email address hidden>
ICQ: 204036003
phone: +79051122311
Tula, Russia (GMT +4)

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

On 05/12/2013 04:48 PM, Alexey Kopytov wrote:

>
> I tried to repeat the test, but your branch doesn't build for me now, it
> fails as follows:
>
> [ 70%] Building CXX object
> libmysqld/CMakeFiles/sql_embedded.dir/__/sql/field_conv.cc.o
> /Users/kaa/src/launchpad/percona-xtrabackup/2.1-apply-archived-logs-innodb5.6/mysql-5.6/storage/innobase/log/log0recv.cc:3142:3:
> error: no matching function for call to
> 'log_checkpoint_get_nth_group_info'
> log_checkpoint_get_nth_group_info(buf, group->id,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /Users/kaa/src/launchpad/percona-xtrabackup/2.1-apply-archived-logs-innodb5.6/mysql-5.6/storage/innobase/include/log0log.h:286:1:
> note: candidate function not viable: no known
> conversion from 'lsn_t *' (aka 'unsigned long long *') to 'ulint
> *' (aka 'unsigned long *') for 3rd argument;
> log_checkpoint_get_nth_group_info(
> ^
> 1[ 70%] error generated.
>

I am preparing the more detailed answer with code fixes so currently I
don't want to commit unfinished changes. But it is possible just to
comment log_checkpoint_get_nth_group_info() invoking at that place
because the values it reads from buffer are not used for logs applying.

--
Vlad Lesin, Software Engineer, Percona Inc.
<email address hidden>
skype: vlad_lesin
JID: <email address hidden>
ICQ: 204036003
phone: +79051122311
Tula, Russia (GMT +4)

Revision history for this message
Alexey Kopytov (akopytov) wrote :

Hi Vlad,

On Mon, 13 May 2013 17:44:36 +0400, Vlad Lesin wrote:
> On 05/12/2013 04:48 PM, Alexey Kopytov wrote:
>>>> - in recv_recovery_from_archive_start() we ignore the
>>>> first_log_no
>>>> argument and use xtrabackup_arch_first_file_lsn instead.
>>>> wouldn't
>>>> it be better to pass xtrabackup_arch_first_file_lsn as the
>>>> first_log_no argument to recv_recovery_from_archive_start()
>>>> and
>
> As I understood our chat right the main cause of this change is to
> remove 'fake' arguments from recv_recovery_from_archive_start().
>
> Why just don't remove first_log_no from
> recv_recovery_from_archive_start() arguments list? I don't see any
> benefits in passing xtrabackup_arch_first_file_lsn and
> xtrabackup_arch_last_file_lsn to recv_recovery_from_archive_start() as
> arguments because in this case we just remove using global external
> variables from recv_recovery_from_archive_start() to
> innobase_start_or_create_for_mysql().
>

Either way is fine by me as long as we avoid fake arguments.

> >>> get rid of min/max_arch_log_no in
> >>> innobase_start_or_create_for_mysql()?
>
> Right. In this case we could remove min/max_arch_log_no from
> open_or_create_data_files() arguments list and from xb_data_files_init()
> too.
>

OK.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> > Why just don't remove first_log_no from
> > recv_recovery_from_archive_start() arguments list? I don't see any
> > benefits in passing xtrabackup_arch_first_file_lsn and
> > xtrabackup_arch_last_file_lsn to recv_recovery_from_archive_start() as
> > arguments because in this case we just remove using global external
> > variables from recv_recovery_from_archive_start() to
> > innobase_start_or_create_for_mysql().
> >
>
> Either way is fine by me as long as we avoid fake arguments.
Done.

> > Right. In this case we could remove min/max_arch_log_no from
> > open_or_create_data_files() arguments list and from xb_data_files_init()
> > too.
> >
>
> OK.
Done.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> Hi Vlad,
>
>
> General comments:
>
> - I think this MP should wait until 5.6.11-60.3 with the fix for bug
> #1172591 is released. Then the test suite should use 5.6.11-60.30
> for testing instead of the custom build
The fix is released.

> - there should be a separate fix for bug #1177182 for both 2.0 and
> 2.1, and again, this branch should be rebased once the fix is merged to
> trunks.
The fix for 2.1 is merged and for 2.0 is approved for merging.

> - xtrabackup_arch_search_files() should use msg() instead of
> fprintf(stderr,...)
Fixed.

> >> - s/alligned to the up of log file block/aligned up to the log
> >> block size/
> >
> > Done.
> >
>
> Not fully done, it is "aligned" (single "l"), not "alligned".
Done.

> OK, I see the problem now, reported as bug #1179193. This means we have
> to fix that bug separately in both 2.0 and 2.1, and then rebase this
> branch on 2.1 trunk with that fix included.
I explored this problem more deeply and found out that the problem is "apply archived log" specific. See my comment to the bug report and
                if (srv_apply_log_only) {
                        goto skip_processes;
                }
strings in innobase_start_or_create_for_mysql().

> >> - the test case doesn't work for me (fails with "table 'test.t1'
> >> doesn't exist" when run against PS 5.6 with log archiving enabled)
> >>
> >
> > I need your assistance here because I can't reproduce this on my
> > environment and, as I understood, on Jenkins environment too(see
> > http://jenkins.percona.com/view/XtraBackup/job/percona-
> xtrabackup-2.1-param/298/#showFailuresLink).
> >
>
> I tried to repeat the test, but your branch doesn't build for me now, it
> fails as follows:
>
> [ 70%] Building CXX object
> libmysqld/CMakeFiles/sql_embedded.dir/__/sql/field_conv.cc.o
> /Users/kaa/src/launchpad/percona-xtrabackup/2.1-apply-archived-logs-
> innodb5.6/mysql-5.6/storage/innobase/log/log0recv.cc:3142:3:
> error: no matching function for call to
> 'log_checkpoint_get_nth_group_info'
> log_checkpoint_get_nth_group_info(buf, group->id,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /Users/kaa/src/launchpad/percona-xtrabackup/2.1-apply-archived-logs-
> innodb5.6/mysql-5.6/storage/innobase/include/log0log.h:286:1:
> note: candidate function not viable: no known
> conversion from 'lsn_t *' (aka 'unsigned long long *') to 'ulint
> *' (aka 'unsigned long *') for 3rd argument;
> log_checkpoint_get_nth_group_info(
> ^
> 1[ 70%] error generated.
Fixed. The invocation of log_checkpoint_get_nth_group_info() is commented in this place because there is no need to read archived_file_no and archived_offset. They are calculated another way.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

Rebased on newest trunk (lp:percona-xtrabackup revision 650).

Revision history for this message
Alexey Kopytov (akopytov) wrote :

I don't think XtraDB-related changes in run.sh are necessary now. Check the is_xtradb()/require_xtradb() functions and how they are used in other tests.

Revision history for this message
Alexey Kopytov (akopytov) wrote :

Oh, and you will also need require_server_version_higher_than()

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

On 07/31/2013 04:54 PM, Alexey Kopytov wrote:
> I don't think XtraDB-related changes in run.sh are necessary now. Check the is_xtradb()/require_xtradb() functions and how they are used in other tests.
>
Yes, you are right, there is no need to change run.sh as server and
innodb flavours are detected right now based on "innodb_version" server
variable.

But require_server_version_higher_than() and
require_xtradb()/require_xtradb() does not suite me because
require_server_version_higher_than() checks only server version but I
need to check server flavour too as well as
require_xtradb()/require_xtradb() checks only the fact of xtradb using
but xtradb version must be checked too.

So I reverted run.sh and fixed xb_apply_archived_logs.sh to use
is_server_version_higher_than() for server version checking.

Revision history for this message
Alexey Kopytov (akopytov) wrote :

Hi Vlad,

On Wed, 31 Jul 2013 21:43:33 -0000, Vlad Lesin wrote:
> But require_server_version_higher_than() and
> require_xtradb()/require_xtradb() does not suite me because
> require_server_version_higher_than() checks only server version but I
> need to check server flavour too as well as
> require_xtradb()/require_xtradb() checks only the fact of xtradb using
> but xtradb version must be checked too.
>

You can do:

require_xtradb
require_server_version_higher_than 5.6.10

Or use is_* functions if you need something complex.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

On 08/01/2013 08:39 AM, Alexey Kopytov wrote:
> Hi Vlad,
>
> On Wed, 31 Jul 2013 21:43:33 -0000, Vlad Lesin wrote:
>> But require_server_version_higher_than() and
>> require_xtradb()/require_xtradb() does not suite me because
>> require_server_version_higher_than() checks only server version but I
>> need to check server flavour too as well as
>> require_xtradb()/require_xtradb() checks only the fact of xtradb using
>> but xtradb version must be checked too.
>>
>
> You can do:
>
> require_xtradb
> require_server_version_higher_than 5.6.10
>
> Or use is_* functions if you need something complex.
>

Yes, but xtradb can be 5.5,5.1 or 5.6. But only 5.6 supports logs applying.

Revision history for this message
Alexey Kopytov (akopytov) wrote :

Hi Vlad,

On Thu, 01 Aug 2013 11:01:56 +0400, Vlad Lesin wrote:
>> You can do:
>>
>> require_xtradb
>> require_server_version_higher_than 5.6.10
>>
>> Or use is_* functions if you need something complex.
>>
>
> Yes, but xtradb can be 5.5,5.1 or 5.6. But only 5.6 supports logs applying.
>

The above 2 lines will make the test run only on XtraDB > 5.6.10?

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Vlad,

Do you have any explanations for multiple test failures and crashes in both builds?

review: Needs Information
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> Vlad,
>
> Do you have any explanations for multiple test failures and crashes in both
> builds?

Yes, there were bug concerned with wrong lsn writing to data files on "prepare" step when logs applying is not used. I fixed it, here is the new test results:
http://jenkins.percona.com/view/XtraBackup/job/percona-xtrabackup-2.1-param/420/

Revision history for this message
Alexey Kopytov (akopytov) wrote :

Vlad,

Approved, but please rebase on the current trunk. I get many conflicts in innodb56.patch. The good news is that it's going to be the last rebase for this branch. Sorry about the stretched review process. Please also do another Jenkins param build after rebasing.

Thanks.

review: Approve
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> Vlad,
>
> Approved, but please rebase on the current trunk. I get many conflicts in
> innodb56.patch. The good news is that it's going to be the last rebase for
> this branch. Sorry about the stretched review process. Please also do another
> Jenkins param build after rebasing.
>
> Thanks.

Done.

http://jenkins.percona.com/view/XtraBackup/job/percona-xtrabackup-2.1-param/443/

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
=== modified file 'patches/innodb56.patch'
--- patches/innodb56.patch 2013-08-20 17:43:45 +0000
+++ patches/innodb56.patch 2013-08-26 07:08:27 +0000
@@ -1564,3 +1564,825 @@
1564 1564
1565 buf = group->checkpoint_buf;1565 buf = group->checkpoint_buf;
1566 1566
1567--- a/storage/innobase/fil/fil0fil.cc
1568+++ b/storage/innobase/fil/fil0fil.cc
1569@@ -1980,12 +1980,6 @@
1570 contain sensible data */
1571 ulint* flags, /*!< out: tablespace flags */
1572 ulint* space_id, /*!< out: tablespace ID */
1573-#ifdef UNIV_LOG_ARCHIVE
1574- ulint* min_arch_log_no, /*!< out: min of archived
1575- log numbers in data files */
1576- ulint* max_arch_log_no, /*!< out: max of archived
1577- log numbers in data files */
1578-#endif /* UNIV_LOG_ARCHIVE */
1579 lsn_t* min_flushed_lsn, /*!< out: min of flushed
1580 lsn values in data files */
1581 lsn_t* max_flushed_lsn) /*!< out: max of flushed
1582@@ -2014,10 +2008,6 @@
1583 if (!one_read_already) {
1584 *min_flushed_lsn = flushed_lsn;
1585 *max_flushed_lsn = flushed_lsn;
1586-#ifdef UNIV_LOG_ARCHIVE
1587- *min_arch_log_no = arch_log_no;
1588- *max_arch_log_no = arch_log_no;
1589-#endif /* UNIV_LOG_ARCHIVE */
1590 return;
1591 }
1592
1593@@ -2027,14 +2017,6 @@
1594 if (*max_flushed_lsn < flushed_lsn) {
1595 *max_flushed_lsn = flushed_lsn;
1596 }
1597-#ifdef UNIV_LOG_ARCHIVE
1598- if (*min_arch_log_no > arch_log_no) {
1599- *min_arch_log_no = arch_log_no;
1600- }
1601- if (*max_arch_log_no < arch_log_no) {
1602- *max_arch_log_no = arch_log_no;
1603- }
1604-#endif /* UNIV_LOG_ARCHIVE */
1605 }
1606
1607 /*================ SINGLE-TABLE TABLESPACES ==========================*/
1608@@ -3538,9 +3520,6 @@
1609 lsn_t lsn; /*!< Flushed LSN from header page */
1610 ulint id; /*!< Space ID */
1611 ulint flags; /*!< Tablespace flags */
1612-#ifdef UNIV_LOG_ARCHIVE
1613- ulint arch_log_no; /*!< latest archived log file number */
1614-#endif /* UNIV_LOG_ARCHIVE */
1615 };
1616
1617 static
1618@@ -3771,9 +3750,6 @@
1619 if (def.success) {
1620 fil_read_first_page(
1621 def.file, FALSE, &def.flags, &def.id,
1622-#ifdef UNIV_LOG_ARCHIVE
1623- &space_arch_log_no, &space_arch_log_no,
1624-#endif /* UNIV_LOG_ARCHIVE */
1625 &def.lsn, &def.lsn);
1626
1627 /* Validate this single-table-tablespace with SYS_TABLES,
1628@@ -3795,9 +3771,6 @@
1629 if (remote.success) {
1630 fil_read_first_page(
1631 remote.file, FALSE, &remote.flags, &remote.id,
1632-#ifdef UNIV_LOG_ARCHIVE
1633- &remote.arch_log_no, &remote.arch_log_no,
1634-#endif /* UNIV_LOG_ARCHIVE */
1635 &remote.lsn, &remote.lsn);
1636
1637 /* Validate this single-table-tablespace with SYS_TABLES,
1638@@ -3820,9 +3793,6 @@
1639 if (dict.success) {
1640 fil_read_first_page(
1641 dict.file, FALSE, &dict.flags, &dict.id,
1642-#ifdef UNIV_LOG_ARCHIVE
1643- &dict.arch_log_no, &dict.arch_log_no,
1644-#endif /* UNIV_LOG_ARCHIVE */
1645 &dict.lsn, &dict.lsn);
1646
1647 /* Validate this single-table-tablespace with SYS_TABLES,
1648@@ -4054,9 +4024,6 @@
1649 {
1650 fil_read_first_page(
1651 fsp->file, FALSE, &fsp->flags, &fsp->id,
1652-#ifdef UNIV_LOG_ARCHIVE
1653- &fsp->arch_log_no, &fsp->arch_log_no,
1654-#endif /* UNIV_LOG_ARCHIVE */
1655 &fsp->lsn, &fsp->lsn);
1656
1657 if (fsp->id == ULINT_UNDEFINED || fsp->id == 0) {
1658
1659--- a/storage/innobase/handler/ha_innodb.cc
1660+++ b/storage/innobase/handler/ha_innodb.cc
1661@@ -2859,12 +2859,9 @@
1662 }
1663
1664 #ifdef UNIV_LOG_ARCHIVE
1665- /* Since innodb_log_arch_dir has no relevance under MySQL,
1666- starting from 4.0.6 we always set it the same as
1667- innodb_log_group_home_dir: */
1668-
1669- innobase_log_arch_dir = innobase_log_group_home_dir;
1670-
1671+ if (!innobase_log_arch_dir) {
1672+ innobase_log_arch_dir = srv_log_group_home_dir;
1673+ }
1674 srv_arch_dir = innobase_log_arch_dir;
1675 #endif /* UNIG_LOG_ARCHIVE */
1676
1677
1678--- a/storage/innobase/include/fil0fil.h
1679+++ b/storage/innobase/include/fil0fil.h
1680@@ -374,12 +374,6 @@
1681 contain sensible data */
1682 ulint* flags, /*!< out: tablespace flags */
1683 ulint* space_id, /*!< out: tablespace ID */
1684-#ifdef UNIV_LOG_ARCHIVE
1685- ulint* min_arch_log_no, /*!< out: min of archived
1686- log numbers in data files */
1687- ulint* max_arch_log_no, /*!< out: max of archived
1688- log numbers in data files */
1689-#endif /* UNIV_LOG_ARCHIVE */
1690 lsn_t* min_flushed_lsn, /*!< out: min of flushed
1691 lsn values in data files */
1692 lsn_t* max_flushed_lsn); /*!< out: max of flushed
1693
1694--- a/storage/innobase/include/log0log.h
1695+++ b/storage/innobase/include/log0log.h
1696@@ -70,6 +70,10 @@
1697 /** Maximum number of log groups in log_group_t::checkpoint_buf */
1698 #define LOG_MAX_N_GROUPS 32
1699
1700+#define IB_ARCHIVED_LOGS_PREFIX "ib_log_archive_"
1701+#define IB_ARCHIVED_LOGS_PREFIX_LEN (sizeof(IB_ARCHIVED_LOGS_PREFIX) - 1)
1702+#define IB_ARCHIVED_LOGS_SERIAL_LEN 20
1703+
1704 /*******************************************************************//**
1705 Calculates where in log files we find a specified lsn.
1706 @return log file number */
1707@@ -340,8 +344,18 @@
1708 log_archived_file_name_gen(
1709 /*=======================*/
1710 char* buf, /*!< in: buffer where to write */
1711+ ulint buf_len,/*!< in: buffer length */
1712 ulint id, /*!< in: group id */
1713- ulint file_no);/*!< in: file number */
1714+ lsn_t file_no);/*!< in: file number */
1715+
1716+UNIV_INTERN
1717+void
1718+log_archived_get_offset(
1719+/*====================*/
1720+ log_group_t* group, /*!< in: log group */
1721+ lsn_t file_no, /*!< in: archive log file number */
1722+ lsn_t archived_lsn, /*!< in: last archived LSN */
1723+ lsn_t* offset); /*!< out: offset within archived file */
1724 #else /* !UNIV_HOTBACKUP */
1725 /******************************************************//**
1726 Writes info to a buffer of a log group when log files are created in
1727@@ -739,19 +753,19 @@
1728 ulint archive_space_id;/*!< file space which
1729 implements the log group
1730 archive */
1731- ulint archived_file_no;/*!< file number corresponding to
1732+ lsn_t archived_file_no;/*!< file number corresponding to
1733 log_sys->archived_lsn */
1734- ulint archived_offset;/*!< file offset corresponding to
1735+ lsn_t archived_offset;/*!< file offset corresponding to
1736 log_sys->archived_lsn, 0 if we have
1737 not yet written to the archive file
1738 number archived_file_no */
1739- ulint next_archived_file_no;/*!< during an archive write,
1740+ lsn_t next_archived_file_no;/*!< during an archive write,
1741 until the write is completed, we
1742 store the next value for
1743 archived_file_no here: the write
1744 completion function then sets the new
1745 value to ..._file_no */
1746- ulint next_archived_offset; /*!< like the preceding field */
1747+ lsn_t next_archived_offset; /*!< like the preceding field */
1748 #endif /* UNIV_LOG_ARCHIVE */
1749 /*-----------------------------*/
1750 lsn_t scanned_lsn; /*!< used only in recovery: recovery scan
1751
1752--- a/storage/innobase/include/log0recv.h
1753+++ b/storage/innobase/include/log0recv.h
1754@@ -297,18 +297,13 @@
1755 Recovers from archived log files, and also from log files, if they exist.
1756 @return error code or DB_SUCCESS */
1757 UNIV_INTERN
1758-ulint
1759+dberr_t
1760 recv_recovery_from_archive_start(
1761 /*=============================*/
1762 lsn_t min_flushed_lsn,/*!< in: min flushed lsn field from the
1763 data files */
1764- lsn_t limit_lsn, /*!< in: recover up to this lsn if
1765+ lsn_t limit_lsn); /*!< in: recover up to this lsn if
1766 possible */
1767- ulint first_log_no); /*!< in: number of the first archived
1768- log file to use in the recovery; the
1769- file will be searched from
1770- INNOBASE_LOG_ARCH_DIR specified in
1771- server config file */
1772 /********************************************************//**
1773 Completes recovery from archive. */
1774 UNIV_INTERN
1775
1776--- a/storage/innobase/include/univ.i
1777+++ b/storage/innobase/include/univ.i
1778@@ -46,6 +46,9 @@
1779 #define INNODB_VERSION_MINOR MYSQL_VERSION_MINOR
1780 #define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH
1781
1782+/* Enable UNIV_LOG_ARCHIVE in XtraDB */
1783+#define UNIV_LOG_ARCHIVE 1
1784+
1785 /* The following is the InnoDB version as shown in
1786 SELECT plugin_version FROM information_schema.plugins;
1787 calculated in make_version_string() in sql/sql_show.cc like this:
1788
1789--- a/storage/innobase/log/log0log.cc
1790+++ b/storage/innobase/log/log0log.cc
1791@@ -896,10 +896,10 @@
1792 mem_zalloc(sizeof(byte**) * n_files));
1793
1794 #ifdef UNIV_LOG_ARCHIVE
1795- group->archive_file_header_bufs_ptr = static_cast<byte*>(
1796+ group->archive_file_header_bufs_ptr = static_cast<byte**>(
1797 mem_zalloc( sizeof(byte*) * n_files));
1798
1799- group->archive_file_header_bufs = static_cast<byte*>(
1800+ group->archive_file_header_bufs = static_cast<byte**>(
1801 mem_zalloc(sizeof(byte*) * n_files));
1802 #endif /* UNIV_LOG_ARCHIVE */
1803
1804@@ -924,7 +924,7 @@
1805 #ifdef UNIV_LOG_ARCHIVE
1806 group->archive_space_id = archive_space_id;
1807
1808- group->archived_file_no = 0;
1809+ group->archived_file_no = LOG_START_LSN;
1810 group->archived_offset = 0;
1811 #endif /* UNIV_LOG_ARCHIVE */
1812
1813@@ -2228,7 +2228,7 @@
1814 fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, 0,
1815 (ulint) (source_offset / UNIV_PAGE_SIZE),
1816 (ulint) (source_offset % UNIV_PAGE_SIZE),
1817- len, buf, NULL);
1818+ len, buf, (type == LOG_ARCHIVE) ? &log_archive_io : NULL);
1819
1820 start_lsn += len;
1821 buf += len;
1822@@ -2247,12 +2247,68 @@
1823 log_archived_file_name_gen(
1824 /*=======================*/
1825 char* buf, /*!< in: buffer where to write */
1826+ ulint buf_len,/*!< in: buffer length */
1827 ulint id __attribute__((unused)),
1828 /*!< in: group id;
1829 currently we only archive the first group */
1830- ulint file_no)/*!< in: file number */
1831-{
1832- sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, (ulong) file_no);
1833+ lsn_t file_no)/*!< in: file number */
1834+{
1835+ ulint dirnamelen;
1836+
1837+ dirnamelen = strlen(srv_arch_dir);
1838+
1839+ ut_a(buf_len > dirnamelen +
1840+ IB_ARCHIVED_LOGS_SERIAL_LEN +
1841+ IB_ARCHIVED_LOGS_PREFIX_LEN + 2);
1842+
1843+ strcpy(buf, srv_arch_dir);
1844+
1845+ if (buf[dirnamelen-1] != SRV_PATH_SEPARATOR) {
1846+ buf[dirnamelen++] = SRV_PATH_SEPARATOR;
1847+ }
1848+ sprintf(buf + dirnamelen, IB_ARCHIVED_LOGS_PREFIX
1849+ "%0" IB_TO_STR(IB_ARCHIVED_LOGS_SERIAL_LEN) "llu",
1850+ file_no);
1851+}
1852+
1853+/******************************************************//**
1854+Get offset within archived log file to continue to write
1855+with. */
1856+UNIV_INTERN
1857+void
1858+log_archived_get_offset(
1859+/*=====================*/
1860+ log_group_t* group, /*!< in: log group */
1861+ lsn_t file_no, /*!< in: archive log file number */
1862+ lsn_t archived_lsn, /*!< in: last archived LSN */
1863+ lsn_t* offset) /*!< out: offset within archived file */
1864+{
1865+ char file_name[OS_FILE_MAX_PATH];
1866+ ibool exists;
1867+ os_file_type_t type;
1868+
1869+ log_archived_file_name_gen(file_name,
1870+ sizeof(file_name), group->id, file_no);
1871+
1872+ ut_a(os_file_status(file_name, &exists, &type));
1873+
1874+ if (!exists) {
1875+ *offset = 0;
1876+ return;
1877+ }
1878+
1879+ *offset = archived_lsn - file_no + LOG_FILE_HDR_SIZE;
1880+
1881+ if (archived_lsn != IB_ULONGLONG_MAX) {
1882+ *offset = archived_lsn - file_no + LOG_FILE_HDR_SIZE;
1883+ } else {
1884+ /* Archiving was OFF prior startup */
1885+ *offset = 0;
1886+ }
1887+
1888+ ut_a(group->file_size >= *offset + LOG_FILE_HDR_SIZE);
1889+
1890+ return;
1891 }
1892
1893 /******************************************************//**
1894@@ -2290,6 +2346,7 @@
1895 MONITOR_INC(MONITOR_LOG_IO);
1896
1897 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id,
1898+ 0,
1899 dest_offset / UNIV_PAGE_SIZE,
1900 dest_offset % UNIV_PAGE_SIZE,
1901 2 * OS_FILE_LOG_BLOCK_SIZE,
1902@@ -2325,6 +2382,7 @@
1903 MONITOR_INC(MONITOR_LOG_IO);
1904
1905 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id,
1906+ 0,
1907 dest_offset / UNIV_PAGE_SIZE,
1908 dest_offset % UNIV_PAGE_SIZE,
1909 OS_FILE_LOG_BLOCK_SIZE,
1910@@ -2379,7 +2437,7 @@
1911 open_mode = OS_FILE_OPEN;
1912 }
1913
1914- log_archived_file_name_gen(name, group->id,
1915+ log_archived_file_name_gen(name, sizeof(name), group->id,
1916 group->archived_file_no + n_files);
1917
1918 file_handle = os_file_create(innodb_file_log_key,
1919@@ -2454,6 +2512,7 @@
1920 MONITOR_INC(MONITOR_LOG_IO);
1921
1922 fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->archive_space_id,
1923+ 0,
1924 (ulint) (next_offset / UNIV_PAGE_SIZE),
1925 (ulint) (next_offset % UNIV_PAGE_SIZE),
1926 ut_calc_align(len, OS_FILE_LOG_BLOCK_SIZE), buf,
1927@@ -2825,7 +2884,6 @@
1928 trunc_len);
1929 if (increment_file_count) {
1930 group->archived_offset = 0;
1931- group->archived_file_no += 2;
1932 }
1933
1934 #ifdef UNIV_DEBUG
1935@@ -3090,7 +3148,6 @@
1936 /*=======================================*/
1937 {
1938 lsn_t lsn;
1939- ulint arch_log_no;
1940 ulint count = 0;
1941 ulint total_trx;
1942 ulint pending_io;
1943@@ -3307,15 +3364,7 @@
1944 goto loop;
1945 }
1946
1947- arch_log_no = 0;
1948-
1949 #ifdef UNIV_LOG_ARCHIVE
1950- UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
1951-
1952- if (0 == UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) {
1953-
1954- arch_log_no--;
1955- }
1956
1957 log_archive_close_groups(TRUE);
1958 #endif /* UNIV_LOG_ARCHIVE */
1959@@ -3374,7 +3423,16 @@
1960 srv_shutdown_lsn = lsn;
1961
1962 if (!srv_read_only_mode) {
1963- fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
1964+ /*
1965+ log_sys->lsn is aligned up to the log block size
1966+ in recv_reset_logs(), but if archived logs are applied
1967+ data files must contain exactly the same flushed_lsn
1968+ on which applying was finished
1969+ */
1970+ fil_write_flushed_lsn_to_data_files(
1971+ srv_archive_recovery ? recv_sys->recovered_lsn :
1972+ lsn,
1973+ 0);
1974
1975 fil_flush_file_spaces(FIL_TABLESPACE);
1976 }
1977@@ -3597,7 +3655,7 @@
1978
1979 #ifdef UNIV_LOG_ARCHIVE
1980 rw_lock_free(&log_sys->archive_lock);
1981- os_event_create();
1982+ os_event_free(log_sys->archiving_on);
1983 #endif /* UNIV_LOG_ARCHIVE */
1984
1985 #ifdef UNIV_LOG_DEBUG
1986
1987--- a/storage/innobase/log/log0recv.cc
1988+++ b/storage/innobase/log/log0recv.cc
1989@@ -53,6 +53,13 @@
1990 //#else /* !UNIV_HOTBACKUP */
1991 #include "xb0xb.h"
1992
1993+/** The size of archived log file */
1994+extern ib_uint64_t xtrabackup_arch_file_size;
1995+/** The minimal LSN of found archived log files */
1996+extern ib_uint64_t xtrabackup_arch_first_file_lsn;
1997+/** The maximum LSN of found archived log files */
1998+extern ib_uint64_t xtrabackup_arch_last_file_lsn;
1999+
2000 /** This is set to FALSE if the backup was originally taken with the
2001 ibbackup --include regexp option: then we do not want to create tables in
2002 directories which were not included */
2003@@ -2866,7 +2873,10 @@
2004 = log_block_get_checkpoint_no(log_block);
2005 }
2006
2007- if (data_len < OS_FILE_LOG_BLOCK_SIZE) {
2008+ /* Stop scanning if scanned lsn reaches lsn limit */
2009+ if (data_len < OS_FILE_LOG_BLOCK_SIZE ||
2010+ (recv_sys->limit_lsn &&
2011+ recv_sys->scanned_lsn >= recv_sys->limit_lsn)) {
2012 /* Log data for this group ends here */
2013
2014 finished = TRUE;
2015@@ -3157,10 +3167,14 @@
2016 group = UT_LIST_GET_FIRST(log_sys->log_groups);
2017
2018 while (group) {
2019+ /* There is no need to read archived_file_no and
2020+ archived_offset because they are calculated another
2021+ way */
2022+ /*
2023 log_checkpoint_get_nth_group_info(buf, group->id,
2024 &(group->archived_file_no),
2025 &(group->archived_offset));
2026-
2027+ */
2028 group = UT_LIST_GET_NEXT(log_groups, group);
2029 }
2030 #endif /* UNIV_LOG_ARCHIVE */
2031@@ -3731,23 +3745,23 @@
2032 ulint len;
2033 ibool ret;
2034 byte* buf;
2035- os_offset_t read_offset;
2036+ os_offset_t read_offset = 0;
2037 os_offset_t file_size;
2038 int input_char;
2039- char name[10000];
2040+ char name[OS_FILE_MAX_PATH];
2041
2042- ut_a(0);
2043
2044 try_open_again:
2045 buf = log_sys->buf;
2046
2047 /* Add the file to the archive file space; open the file */
2048
2049- log_archived_file_name_gen(name, group->id, group->archived_file_no);
2050+ log_archived_file_name_gen(name, sizeof(name),
2051+ group->id, group->archived_file_no);
2052
2053 file_handle = os_file_create(innodb_file_log_key,
2054 name, OS_FILE_OPEN,
2055- OS_FILE_LOG, OS_FILE_AIO, &ret);
2056+ OS_FILE_AIO, OS_LOG_FILE, &ret);
2057
2058 if (ret == FALSE) {
2059 ask_again:
2060@@ -3792,20 +3806,19 @@
2061
2062 /* Add the archive file as a node to the space */
2063
2064- fil_node_create(name, 1 + file_size / UNIV_PAGE_SIZE,
2065- group->archive_space_id, FALSE);
2066-#if RECV_SCAN_SIZE < LOG_FILE_HDR_SIZE
2067-# error "RECV_SCAN_SIZE < LOG_FILE_HDR_SIZE"
2068-#endif
2069+ ut_a(fil_node_create(name, 1 + file_size / UNIV_PAGE_SIZE,
2070+ group->archive_space_id, FALSE));
2071+ ut_a(RECV_SCAN_SIZE >= LOG_FILE_HDR_SIZE);
2072
2073 /* Read the archive file header */
2074- fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->archive_space_id, 0, 0,
2075+ fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->archive_space_id, 0,
2076+ 0, 0,
2077 LOG_FILE_HDR_SIZE, buf, NULL);
2078
2079 /* Check if the archive file header is consistent */
2080
2081 if (mach_read_from_4(buf + LOG_GROUP_ID) != group->id
2082- || mach_read_from_4(buf + LOG_FILE_NO)
2083+ || mach_read_from_8(buf + LOG_FILE_START_LSN)
2084 != group->archived_file_no) {
2085 fprintf(stderr,
2086 "InnoDB: Archive file header inconsistent %s\n", name);
2087@@ -3834,6 +3847,20 @@
2088 return(TRUE);
2089 }
2090
2091+ /*
2092+ if this is the first file of scanning set
2093+ calculate offset of the first log record
2094+ */
2095+ if (recv_sys->parse_start_lsn >= start_lsn &&
2096+ recv_sys->parse_start_lsn < file_end_lsn) {
2097+ read_offset = ut_calc_align_down(
2098+ recv_sys->parse_start_lsn - start_lsn,
2099+ OS_FILE_LOG_BLOCK_SIZE);
2100+ start_lsn = ut_calc_align_down(
2101+ recv_sys->parse_start_lsn,
2102+ OS_FILE_LOG_BLOCK_SIZE);
2103+ }
2104+
2105 recv_sys->scanned_lsn = start_lsn;
2106 }
2107
2108@@ -3846,7 +3873,7 @@
2109 return(TRUE);
2110 }
2111
2112- read_offset = LOG_FILE_HDR_SIZE;
2113+ read_offset += LOG_FILE_HDR_SIZE;
2114
2115 for (;;) {
2116 len = RECV_SCAN_SIZE;
2117@@ -3872,7 +3899,7 @@
2118 #endif /* UNIV_DEBUG */
2119
2120 fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE,
2121- group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
2122+ group->archive_space_id, 0, read_offset / UNIV_PAGE_SIZE,
2123 read_offset % UNIV_PAGE_SIZE, len, buf, NULL);
2124
2125 ret = recv_scan_log_recs(
2126@@ -3887,10 +3914,12 @@
2127 }
2128
2129 if (ret) {
2130- fprintf(stderr,
2131- "InnoDB: Archive log file %s"
2132- " does not scan right\n",
2133- name);
2134+ if (recv_sys->scanned_lsn < recv_sys->limit_lsn) {
2135+ fprintf(stderr,
2136+ "InnoDB: Archive log file %s"
2137+ " does not scan right\n",
2138+ name);
2139+ }
2140 return(TRUE);
2141 }
2142
2143@@ -3907,26 +3936,19 @@
2144 Recovers from archived log files, and also from log files, if they exist.
2145 @return error code or DB_SUCCESS */
2146 UNIV_INTERN
2147-ulint
2148+dberr_t
2149 recv_recovery_from_archive_start(
2150 /*=============================*/
2151 ib_uint64_t min_flushed_lsn,/*!< in: min flushed lsn field from the
2152 data files */
2153- ib_uint64_t limit_lsn, /*!< in: recover up to this lsn if
2154+ ib_uint64_t limit_lsn) /*!< in: recover up to this lsn if
2155 possible */
2156- ulint first_log_no) /*!< in: number of the first archived
2157- log file to use in the recovery; the
2158- file will be searched from
2159- INNOBASE_LOG_ARCH_DIR specified in
2160- server config file */
2161 {
2162 log_group_t* group;
2163 ulint group_id;
2164 ulint trunc_len;
2165 ibool ret;
2166- ulint err;
2167-
2168- ut_a(0);
2169+ dberr_t err;
2170
2171 recv_sys_create();
2172 recv_sys_init(buf_pool_get_curr_size());
2173@@ -3956,7 +3978,7 @@
2174 return(DB_ERROR);
2175 }
2176
2177- group->archived_file_no = first_log_no;
2178+ group->archived_file_no = xtrabackup_arch_first_file_lsn;
2179
2180 recv_sys->parse_start_lsn = min_flushed_lsn;
2181
2182@@ -3970,7 +3992,8 @@
2183
2184 mutex_enter(&(log_sys->mutex));
2185
2186- while (!ret) {
2187+ while (!ret &&
2188+ group->archived_file_no <= xtrabackup_arch_last_file_lsn) {
2189 ret = log_group_recover_from_archive_file(group);
2190
2191 /* Close and truncate a possible processed archive file
2192@@ -3983,9 +4006,9 @@
2193 trunc_len);
2194 }
2195
2196- group->archived_file_no++;
2197+ group->archived_file_no += group->file_size - LOG_FILE_HDR_SIZE;
2198 }
2199-
2200+/*
2201 if (recv_sys->recovered_lsn < limit_lsn) {
2202
2203 if (!recv_sys->scanned_lsn) {
2204@@ -4006,12 +4029,12 @@
2205
2206 mutex_enter(&(log_sys->mutex));
2207 }
2208-
2209+*/
2210 if (limit_lsn != IB_ULONGLONG_MAX) {
2211
2212 recv_apply_hashed_log_recs(FALSE);
2213
2214- recv_reset_logs(0, FALSE, recv_sys->recovered_lsn);
2215+ // recv_reset_logs(0, FALSE, recv_sys->recovered_lsn);
2216 }
2217
2218 mutex_exit(&(log_sys->mutex));
2219
2220--- a/storage/innobase/srv/srv0start.cc
2221+++ b/storage/innobase/srv/srv0start.cc
2222@@ -641,6 +641,12 @@
2223 }
2224 }
2225
2226+#ifdef UNIV_LOG_ARCHIVE
2227+ /* Create the file space object for archived logs. */
2228+ fil_space_create("arch_log_space", SRV_LOG_SPACE_FIRST_ID + 1,
2229+ 0, FIL_LOG);
2230+#endif
2231+
2232 log_group_init(0, srv_n_log_files,
2233 srv_log_file_size * UNIV_PAGE_SIZE,
2234 SRV_LOG_SPACE_FIRST_ID,
2235@@ -651,7 +657,12 @@
2236 /* Create a log checkpoint. */
2237 mutex_enter(&log_sys->mutex);
2238 ut_d(recv_no_log_write = FALSE);
2239- recv_reset_logs(lsn);
2240+ recv_reset_logs(
2241+#ifdef UNIV_LOG_ARCHIVE
2242+ UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no,
2243+ TRUE,
2244+#endif
2245+ lsn);
2246 mutex_exit(&log_sys->mutex);
2247
2248 return(DB_SUCCESS);
2249@@ -738,12 +749,6 @@
2250 /*======================*/
2251 ibool* create_new_db, /*!< out: TRUE if new database should be
2252 created */
2253-#ifdef UNIV_LOG_ARCHIVE
2254- ulint* min_arch_log_no,/*!< out: min of archived log
2255- numbers in data files */
2256- ulint* max_arch_log_no,/*!< out: max of archived log
2257- numbers in data files */
2258-#endif /* UNIV_LOG_ARCHIVE */
2259 lsn_t* min_flushed_lsn,/*!< out: min of flushed lsn
2260 values in data files */
2261 lsn_t* max_flushed_lsn,/*!< out: max of flushed lsn
2262@@ -964,9 +969,6 @@
2263 skip_size_check:
2264 fil_read_first_page(
2265 files[i], one_opened, &flags, &space,
2266-#ifdef UNIV_LOG_ARCHIVE
2267- min_arch_log_no, max_arch_log_no,
2268-#endif /* UNIV_LOG_ARCHIVE */
2269 min_flushed_lsn, max_flushed_lsn);
2270
2271 /* The first file of the system tablespace must
2272@@ -1450,8 +1452,8 @@
2273 lsn_t min_flushed_lsn;
2274 lsn_t max_flushed_lsn;
2275 #ifdef UNIV_LOG_ARCHIVE
2276- ulint min_arch_log_no;
2277- ulint max_arch_log_no;
2278+ lsn_t min_arch_log_no;
2279+ lsn_t max_arch_log_no;
2280 #endif /* UNIV_LOG_ARCHIVE */
2281 ulint sum_of_new_sizes;
2282 ulint sum_of_data_file_sizes;
2283@@ -1890,17 +1892,6 @@
2284 os_thread_create(io_handler_thread, n + i, thread_ids + i);
2285 }
2286
2287-#ifdef UNIV_LOG_ARCHIVE
2288- if (0 != ut_strcmp(srv_log_group_home_dir, srv_arch_dir)) {
2289- ut_print_timestamp(stderr);
2290- fprintf(stderr, " InnoDB: Error: you must set the log group home dir in my.cnf\n");
2291- ut_print_timestamp(stderr);
2292- fprintf(stderr, " InnoDB: the same as log arch dir.\n");
2293-
2294- return(DB_ERROR);
2295- }
2296-#endif /* UNIV_LOG_ARCHIVE */
2297-
2298 if (srv_n_log_files * srv_log_file_size * UNIV_PAGE_SIZE
2299 >= 512ULL * 1024ULL * 1024ULL * 1024ULL) {
2300 /* log_block_convert_lsn_to_no() limits the returned block
2301@@ -1959,9 +1950,6 @@
2302 }
2303
2304 err = open_or_create_data_files(&create_new_db,
2305-#ifdef UNIV_LOG_ARCHIVE
2306- &min_arch_log_no, &max_arch_log_no,
2307-#endif /* UNIV_LOG_ARCHIVE */
2308 &min_flushed_lsn, &max_flushed_lsn,
2309 &sum_of_new_sizes);
2310 if (err == DB_FAIL) {
2311@@ -1989,7 +1977,6 @@
2312
2313 #ifdef UNIV_LOG_ARCHIVE
2314 srv_normalize_path_for_win(srv_arch_dir);
2315- srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir);
2316 #endif /* UNIV_LOG_ARCHIVE */
2317
2318 dirnamelen = strlen(srv_log_group_home_dir);
2319@@ -2068,9 +2055,15 @@
2320 max_flushed_lsn, logfile0);
2321
2322 /* Suppress the message about
2323- crash recovery. */
2324- max_flushed_lsn = min_flushed_lsn
2325- = log_get_lsn();
2326+ crash recovery. If archive recovery
2327+ is enabled the min/max_flushed_lsn
2328+ must point to the position from
2329+ which applying is started. */
2330+ if (!srv_archive_recovery) {
2331+ max_flushed_lsn = min_flushed_lsn
2332+ = log_get_lsn();
2333+ }
2334+
2335 goto files_checked;
2336 #if 0
2337 } else if (i < 2) {
2338@@ -2244,10 +2237,13 @@
2339
2340 ib_logf(IB_LOG_LEVEL_INFO,
2341 " Starting archive recovery from a backup...");
2342+ /* Load table spaces before recovery as during recovery
2343+ there can be log records that are applied to the spaces
2344+ with unknown id's */
2345+ fil_load_single_table_tablespaces(NULL);
2346
2347 err = recv_recovery_from_archive_start(
2348- min_flushed_lsn, srv_archive_recovery_limit_lsn,
2349- min_arch_log_no);
2350+ min_flushed_lsn, srv_archive_recovery_limit_lsn);
2351 if (err != DB_SUCCESS) {
2352
2353 return(DB_ERROR);
2354@@ -2271,6 +2267,11 @@
2355 srv_startup_is_before_trx_rollback_phase = FALSE;
2356
2357 recv_recovery_from_archive_finish();
2358+
2359+ if (srv_apply_log_only) {
2360+ goto skip_processes;
2361+ }
2362+
2363 #endif /* UNIV_LOG_ARCHIVE */
2364 } else {
2365
2366@@ -2478,6 +2479,8 @@
2367 if (!srv_log_archive_on) {
2368 ut_a(DB_SUCCESS == log_archive_noarchivelog());
2369 } else {
2370+ bool start_archive;
2371+
2372 mutex_enter(&(log_sys->mutex));
2373
2374 start_archive = FALSE;
2375
2376--- a/storage/innobase/trx/trx0sys.cc
2377+++ b/storage/innobase/trx/trx0sys.cc
2378@@ -1185,7 +1185,8 @@
2379 trx_purge_sys_close();
2380
2381 /* Free the double write data structures. */
2382- buf_dblwr_free();
2383+ if (buf_dblwr)
2384+ buf_dblwr_free();
2385
2386 mutex_enter(&trx_sys->mutex);
2387
2388
15672389
=== modified file 'src/xtrabackup.cc'
--- src/xtrabackup.cc 2013-08-20 17:43:45 +0000
+++ src/xtrabackup.cc 2013-08-26 07:08:27 +0000
@@ -118,6 +118,8 @@
118char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */118char *xtrabackup_extra_lsndir = NULL; /* for --backup with --extra-lsndir */
119char *xtrabackup_incremental_dir = NULL; /* for --prepare */119char *xtrabackup_incremental_dir = NULL; /* for --prepare */
120120
121lsn_t xtrabackup_archived_to_lsn = 0; /* for --archived-to-lsn */
122
121char *xtrabackup_tables = NULL;123char *xtrabackup_tables = NULL;
122int tables_regex_num;124int tables_regex_num;
123xb_regex_t *tables_regex;125xb_regex_t *tables_regex;
@@ -279,6 +281,17 @@
279281
280static my_bool xtrabackup_incremental_force_scan = FALSE;282static my_bool xtrabackup_incremental_force_scan = FALSE;
281283
284/* The flushed lsn which is read from data files */
285lsn_t min_flushed_lsn= 0;
286lsn_t max_flushed_lsn= 0;
287
288/* The size of archived log file */
289size_t xtrabackup_arch_file_size = 0ULL;
290/* The minimal LSN of found archived log files */
291lsn_t xtrabackup_arch_first_file_lsn = 0ULL;
292/* The maximum LSN of found archived log files */
293lsn_t xtrabackup_arch_last_file_lsn = 0ULL;
294
282/* Datasinks */295/* Datasinks */
283ds_ctxt_t *ds_data = NULL;296ds_ctxt_t *ds_data = NULL;
284ds_ctxt_t *ds_meta = NULL;297ds_ctxt_t *ds_meta = NULL;
@@ -388,6 +401,7 @@
388 OPT_XTRA_INCREMENTAL_BASEDIR,401 OPT_XTRA_INCREMENTAL_BASEDIR,
389 OPT_XTRA_EXTRA_LSNDIR,402 OPT_XTRA_EXTRA_LSNDIR,
390 OPT_XTRA_INCREMENTAL_DIR,403 OPT_XTRA_INCREMENTAL_DIR,
404 OPT_XTRA_ARCHIVED_TO_LSN,
391 OPT_XTRA_TABLES,405 OPT_XTRA_TABLES,
392 OPT_XTRA_TABLES_FILE,406 OPT_XTRA_TABLES_FILE,
393 OPT_XTRA_CREATE_IB_LOGFILE,407 OPT_XTRA_CREATE_IB_LOGFILE,
@@ -551,6 +565,12 @@
551 {"incremental-dir", OPT_XTRA_INCREMENTAL_DIR, "(for --prepare): apply .delta files and logfile in the specified directory.",565 {"incremental-dir", OPT_XTRA_INCREMENTAL_DIR, "(for --prepare): apply .delta files and logfile in the specified directory.",
552 (G_PTR*) &xtrabackup_incremental_dir, (G_PTR*) &xtrabackup_incremental_dir,566 (G_PTR*) &xtrabackup_incremental_dir, (G_PTR*) &xtrabackup_incremental_dir,
553 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},567 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
568#ifdef UNIV_LOG_ARCHIVE
569 {"to-archived-lsn", OPT_XTRA_ARCHIVED_TO_LSN,
570 "Don't apply archived logs with bigger log sequence number.",
571 (G_PTR*) &xtrabackup_archived_to_lsn, (G_PTR*) &xtrabackup_archived_to_lsn, 0,
572 GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0},
573#endif /* UNIV_LOG_ARCHIVE */
554 {"tables", OPT_XTRA_TABLES, "filtering by regexp for table names.",574 {"tables", OPT_XTRA_TABLES, "filtering by regexp for table names.",
555 (G_PTR*) &xtrabackup_tables, (G_PTR*) &xtrabackup_tables,575 (G_PTR*) &xtrabackup_tables, (G_PTR*) &xtrabackup_tables,
556 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},576 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -733,11 +753,11 @@
733 (G_PTR*) &innobase_locks_unsafe_for_binlog,753 (G_PTR*) &innobase_locks_unsafe_for_binlog,
734 (G_PTR*) &innobase_locks_unsafe_for_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},754 (G_PTR*) &innobase_locks_unsafe_for_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
735*/755*/
736/*756#ifdef UNIV_LOG_ARCHIVE
737 {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,757 {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,
738 "Where full logs should be archived.", (G_PTR*) &innobase_log_arch_dir,758 "Where full logs should be archived.", (G_PTR*) &innobase_log_arch_dir,
739 (G_PTR*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},759 (G_PTR*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
740*/760#endif /* UNIV_LOG_ARCHIVE */
741 {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,761 {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,
742 "The size of the buffer which InnoDB uses to write log to the log files on disk.",762 "The size of the buffer which InnoDB uses to write log to the log files on disk.",
743 (G_PTR*) &innobase_log_buffer_size, (G_PTR*) &innobase_log_buffer_size, 0,763 (G_PTR*) &innobase_log_buffer_size, (G_PTR*) &innobase_log_buffer_size, 0,
@@ -2573,8 +2593,6 @@
2573 ibool create_new_doublewrite_file;2593 ibool create_new_doublewrite_file;
2574#endif2594#endif
2575 ulint err;2595 ulint err;
2576 lsn_t min_flushed_lsn;
2577 lsn_t max_flushed_lsn;
2578 ulint sum_of_new_sizes;2596 ulint sum_of_new_sizes;
25792597
2580 for (i = 0; i < srv_n_file_io_threads; i++) {2598 for (i = 0; i < srv_n_file_io_threads; i++) {
@@ -5146,6 +5164,76 @@
51465164
5147}5165}
51485166
5167#ifdef UNIV_LOG_ARCHIVE
5168/********************************************************************//**
5169Searches archived log files in archived log directory. The min and max
5170LSN's of found files as well as archived log file size are stored in
5171xtrabackup_arch_first_file_lsn, xtrabackup_arch_last_file_lsn and
5172xtrabackup_arch_file_size respectively.
5173@return true on success
5174*/
5175static
5176bool
5177xtrabackup_arch_search_files(
5178/*=========================*/
5179 ib_uint64_t start_lsn) /*!< in: filter out log files
5180 witch does not contain data
5181 with lsn < start_lsn */
5182{
5183 os_file_dir_t dir;
5184 os_file_stat_t fileinfo;
5185 ut_ad(innobase_log_arch_dir);
5186
5187 dir = os_file_opendir(innobase_log_arch_dir, FALSE);
5188 if (!dir) {
5189 msg("xtrabackup: error: cannot open archived log directory %s\n",
5190 innobase_log_arch_dir);
5191 return false;
5192 }
5193
5194 while(!os_file_readdir_next_file(innobase_log_arch_dir,
5195 dir,
5196 &fileinfo) ) {
5197 lsn_t log_file_lsn;
5198 char* log_str_end_lsn_ptr;
5199
5200 if (strncmp(fileinfo.name,
5201 IB_ARCHIVED_LOGS_PREFIX,
5202 sizeof(IB_ARCHIVED_LOGS_PREFIX) - 1)) {
5203 continue;
5204 }
5205
5206 log_file_lsn = strtoll(fileinfo.name +
5207 sizeof(IB_ARCHIVED_LOGS_PREFIX) - 1,
5208 &log_str_end_lsn_ptr, 10);
5209
5210 if (*log_str_end_lsn_ptr) {
5211 continue;
5212 }
5213
5214 if (log_file_lsn + (fileinfo.size - LOG_FILE_HDR_SIZE) < start_lsn) {
5215 continue;
5216 }
5217
5218 if (!xtrabackup_arch_first_file_lsn ||
5219 log_file_lsn < xtrabackup_arch_first_file_lsn) {
5220 xtrabackup_arch_first_file_lsn = log_file_lsn;
5221 }
5222 if (log_file_lsn > xtrabackup_arch_last_file_lsn) {
5223 xtrabackup_arch_last_file_lsn = log_file_lsn;
5224 }
5225
5226 //TODO: find the more suitable way to extract archived log file
5227 //size
5228 if (fileinfo.size > (ib_int64_t)xtrabackup_arch_file_size) {
5229 xtrabackup_arch_file_size = fileinfo.size;
5230 }
5231 }
5232
5233 return xtrabackup_arch_first_file_lsn != 0;
5234}
5235#endif /* UNIV_LOG_ARCHIVE */
5236
5149static void5237static void
5150xtrabackup_prepare_func(void)5238xtrabackup_prepare_func(void)
5151{5239{
@@ -5169,14 +5257,18 @@
5169 xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here5257 xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here
5170 xtrabackup_target_dir[1]=0;5258 xtrabackup_target_dir[1]=0;
51715259
5172 /* read metadata of target */5260 /*
5261 read metadata of target, we don't need metadata reading in the case
5262 archived logs applying
5263 */
5264 sprintf(metadata_path, "%s/%s", xtrabackup_target_dir,
5265 XTRABACKUP_METADATA_FILENAME);
5266
5267 if (!xtrabackup_read_metadata(metadata_path))
5268 msg("xtrabackup: error: xtrabackup_read_metadata()\n");
5269
5270 if (!innobase_log_arch_dir)
5173 {5271 {
5174 sprintf(metadata_path, "%s/%s", xtrabackup_target_dir,
5175 XTRABACKUP_METADATA_FILENAME);
5176
5177 if (!xtrabackup_read_metadata(metadata_path))
5178 msg("xtrabackup: error: xtrabackup_read_metadata()\n");
5179
5180 if (!strcmp(metadata_type, "full-backuped")) {5272 if (!strcmp(metadata_type, "full-backuped")) {
5181 msg("xtrabackup: This target seems to be not prepared "5273 msg("xtrabackup: This target seems to be not prepared "
5182 "yet.\n");5274 "yet.\n");
@@ -5220,7 +5312,7 @@
5220 mem_init(srv_mem_pool_size);5312 mem_init(srv_mem_pool_size);
5221 ut_crc32_init();5313 ut_crc32_init();
52225314
5223 if(xtrabackup_init_temp_log())5315 if(!innobase_log_arch_dir && xtrabackup_init_temp_log())
5224 goto error;5316 goto error;
52255317
5226 if(innodb_init_param()) {5318 if(innodb_init_param()) {
@@ -5248,14 +5340,15 @@
52485340
5249 xb_normalize_init_values();5341 xb_normalize_init_values();
52505342
5251 if (xtrabackup_incremental) {5343 if (xtrabackup_incremental || innobase_log_arch_dir) {
5252 err = xb_data_files_init();5344 err = xb_data_files_init();
5253 if (err != DB_SUCCESS) {5345 if (err != DB_SUCCESS) {
5254 msg("xtrabackup: error: xb_data_files_init() failed "5346 msg("xtrabackup: error: xb_data_files_init() failed "
5255 "with error code %lu\n", err);5347 "with error code %lu\n", err);
5256 goto error;5348 goto error;
5257 }5349 }
52585350 }
5351 if (xtrabackup_incremental) {
5259 inc_dir_tables_hash = hash_create(1000);5352 inc_dir_tables_hash = hash_create(1000);
52605353
5261 if(!xtrabackup_apply_deltas()) {5354 if(!xtrabackup_apply_deltas()) {
@@ -5263,9 +5356,11 @@
5263 xb_tables_hash_free(inc_dir_tables_hash);5356 xb_tables_hash_free(inc_dir_tables_hash);
5264 goto error;5357 goto error;
5265 }5358 }
52665359 }
5360 if (xtrabackup_incremental || innobase_log_arch_dir) {
5267 xb_data_files_close();5361 xb_data_files_close();
52685362 }
5363 if (xtrabackup_incremental) {
5269 /* Cleanup datadir from tablespaces deleted between full and5364 /* Cleanup datadir from tablespaces deleted between full and
5270 incremental backups */5365 incremental backups */
52715366
@@ -5295,6 +5390,55 @@
5295 srv_n_write_io_threads = 4;5390 srv_n_write_io_threads = 4;
5296 }5391 }
52975392
5393#ifdef UNIV_LOG_ARCHIVE
5394 if (innobase_log_arch_dir) {
5395 srv_arch_dir = innobase_log_arch_dir;
5396 srv_archive_recovery = TRUE;
5397 if (xtrabackup_archived_to_lsn) {
5398 if (xtrabackup_archived_to_lsn < metadata_last_lsn) {
5399 msg("xtrabackup: warning: logs applying lsn "
5400 "limit " UINT64PF " is "
5401 "less than metadata last-lsn " UINT64PF
5402 " and will be set to metadata last-lsn value\n",
5403 xtrabackup_archived_to_lsn,
5404 metadata_last_lsn);
5405 xtrabackup_archived_to_lsn = metadata_last_lsn;
5406 }
5407 if (xtrabackup_archived_to_lsn < min_flushed_lsn) {
5408 msg("xtrabackup: error: logs applying "
5409 "lsn limit " UINT64PF " is less than "
5410 "min_flushed_lsn " UINT64PF
5411 ", there is nothing to do\n",
5412 xtrabackup_archived_to_lsn,
5413 min_flushed_lsn);
5414 goto error;
5415 }
5416 }
5417 srv_archive_recovery_limit_lsn= xtrabackup_archived_to_lsn;
5418 /*
5419 Unfinished transactions are not rolled back during log applying
5420 as they can be finished at the firther files applyings.
5421 */
5422 srv_apply_log_only = TRUE;
5423
5424 if (!xtrabackup_arch_search_files(min_flushed_lsn)) {
5425 goto error;
5426 }
5427
5428 /*
5429 Check if last log file last lsn is big enough to overlap
5430 last scanned lsn read from metadata.
5431 */
5432 if (xtrabackup_arch_last_file_lsn +
5433 xtrabackup_arch_file_size -
5434 LOG_FILE_HDR_SIZE < metadata_last_lsn) {
5435 msg("xtrabackup: error: there are no enough archived logs "
5436 "to apply\n");
5437 goto error;
5438 }
5439 }
5440#endif /* UNIV_LOG_ARCHIVE */
5441
5298 msg("xtrabackup: Starting InnoDB instance for recovery.\n"5442 msg("xtrabackup: Starting InnoDB instance for recovery.\n"
5299 "xtrabackup: Using %lld bytes for buffer pool "5443 "xtrabackup: Using %lld bytes for buffer pool "
5300 "(set by --use-memory parameter)\n", xtrabackup_use_memory);5444 "(set by --use-memory parameter)\n", xtrabackup_use_memory);
@@ -5517,7 +5661,10 @@
5517 "'xtrabackup_binlog_pos_innodb'\n");5661 "'xtrabackup_binlog_pos_innodb'\n");
5518 }5662 }
5519 }5663 }
55205664#ifdef UNIV_LOG_ARCHIVE
5665 if (innobase_log_arch_dir)
5666 srv_start_lsn = log_sys->lsn = recv_sys->recovered_lsn;
5667#endif /* UNIV_LOG_ARCHIVE */
5521 /* Check whether the log is applied enough or not. */5668 /* Check whether the log is applied enough or not. */
5522 if ((xtrabackup_incremental5669 if ((xtrabackup_incremental
5523 && ut_dulint_cmp(srv_start_lsn, incremental_last_lsn) < 0)5670 && ut_dulint_cmp(srv_start_lsn, incremental_last_lsn) < 0)
@@ -5829,6 +5976,14 @@
5829 exit(EXIT_FAILURE);5976 exit(EXIT_FAILURE);
5830 }5977 }
58315978
5979 if (!xtrabackup_prepare &&
5980 (innobase_log_arch_dir || xtrabackup_archived_to_lsn)) {
5981 msg("xtrabackup: error: "
5982 "--archived-logs-dir and --to-archived-lsn can be used "
5983 "only with --prepare\n");
5984 exit(EXIT_FAILURE);
5985 }
5986
5832 /* cannot execute both for now */5987 /* cannot execute both for now */
5833 {5988 {
5834 int num = 0;5989 int num = 0;
58355990
=== added file 'test/t/xb_apply_archived_logs.sh'
--- test/t/xb_apply_archived_logs.sh 1970-01-01 00:00:00 +0000
+++ test/t/xb_apply_archived_logs.sh 2013-08-26 07:08:27 +0000
@@ -0,0 +1,389 @@
1. inc/common.sh
2
3#The result to return
4RESULT=0
5
6function repeat_until_new_arch_log_created
7{
8 local arch_log_dir=$1
9 local command=$2
10 local stop_lsn=`run_cmd $MYSQL $MYSQL_ARGS test -e 'SHOW ENGINE INNODB STATUS\G'|grep 'Log sequence number'|awk '{print $4}'`
11 local old_arch_logs_count=`ls -al $arch_log_dir/| wc -l`
12 local new_arch_logs_count=0
13
14 echo $old_arch_logs_count
15 # To be sure the data was flushed to archived log wait until new file
16 # with START_LSN > CURRENT_LSN is created
17 local max_lsn=0;
18 while [ $max_lsn -le $stop_lsn ];
19 do
20 $command
21 for i in `ls -1 $arch_log_dir`;
22 do
23 local lsn=`echo $i | sed -s 's/ib_log_archive_\([0-9]\+\)/\1/'`
24 if [ $lsn -gt $max_lsn ];
25 then
26 max_lsn=$lsn
27 fi
28 done
29 done
30}
31
32function check_if_equal
33{
34 local NAME=$1
35 local VAL1=$2
36 local VAL2=$3
37 local MSG="$NAME ($VAL1 == $VAL2):"
38 if [ $VAL1 -ne $VAL2 ]
39 then
40 vlog "$MSG failed"
41 RESULT=-1
42 else
43 vlog "$MSG passed"
44 fi
45}
46
47function check_if_not_equal
48{
49 local NAME=$1
50 local VAL1=$2
51 local VAL2=$3
52 local MSG="$NAME ($VAL1 != $VAL2):"
53 if [ $VAL1 -eq $VAL2 ]
54 then
55 vlog "$MSG failed"
56 RESULT=-1
57 else
58 vlog "$MSG passed"
59 fi
60}
61
62function fill_tables
63{
64 local TABLES_COUNT=$1
65 local TABLE_NAME=$2
66
67 for i in `seq 1 $TABLES_COUNT`; do
68 local TN=$TABLE_NAME$i
69 run_cmd $MYSQL $MYSQL_ARGS test \
70<<EOF
71 INSERT INTO $TN (B)
72 SELECT ${TN}_1.B FROM
73 $TN ${TN}_1,
74 $TN ${TN}_2,
75 $TN ${TN}_3
76 LIMIT 10000;
77
78EOF
79 done
80}
81
82function create_and_fill_db
83{
84 local TABLES_COUNT=$1
85 local TABLE_NAME=$2
86 local ARCH_LOG_DIR=$3
87 local CREATE_TABLE_OPTIONS=${4:-''}
88
89 for i in `seq 1 $TABLES_COUNT`; do
90 local TN=$TABLE_NAME$i
91
92 run_cmd $MYSQL $MYSQL_ARGS test \
93<<EOF
94 CREATE TABLE $TN
95 (A INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
96 B INT(10) UNSIGNED NOT NULL DEFAULT 0) ENGINE=INNODB $CREATE_TABLE_OPTIONS;
97 INSERT INTO $TN (B) VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
98 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
99 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
100 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
101 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
102 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
103 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
104 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
105 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),
106 (1),(1),(1),(1),(1),(1),(1),(1),(1),(1);
107EOF
108 done
109
110 repeat_until_new_arch_log_created \
111 $ARCH_LOG_DIR \
112 "fill_tables $TABLES_COUNT $TABLE_NAME"
113}
114
115function make_changes
116{
117 local START_I=$1
118 local TABLES_COUNT=$2
119 local TABLE_NAME=$3
120 local CLIENT_CMD="${MYSQL} ${MYSQL_ARGS} -Ns test -e"
121
122 for i in `seq $START_I $(($START_I+$TABLES_COUNT-1))`; do
123 local TN=$TABLE_NAME$(($i-$START_I+1))
124
125 #INSERT
126 I_FROM[$i]=`$CLIENT_CMD "select max(a) from $TN"`
127 $CLIENT_CMD "insert into $TN (b) select b from $TN limit 1000"
128 I_TO[$i]=`$CLIENT_CMD "select max(a) from $TN"`
129 vlog "Inserted rows for $i are in the range [${I_FROM[$i]}, ${I_TO[$i]})"
130 I_COUNT[$i]=`$CLIENT_CMD "select count(*) from $TN where a >= ${I_FROM[$i]} and a < ${I_TO[$i]} "`
131
132 #DELETE
133 if [ $i -gt $TABLES_COUNT ];
134 then
135 local START_ROW=${U_TO[$(($i-$TABLES_COUNT))]}
136 else
137 local START_ROW=1000
138 fi
139 D_FROM[$i]=`$CLIENT_CMD "select min(a) from (select a from $TN where a >= $START_ROW limit 1000) as temp_table"`
140 D_TO[$i]=`$CLIENT_CMD "select max(a) from (select a from $TN where a >= $START_ROW limit 1000) as temp_table"`
141 D_COUNT[$i]=`$CLIENT_CMD "select count(*) from $TN where a>=${D_FROM[$i]} and a<${D_TO[$i]}"`
142 $CLIENT_CMD "delete from $TN where a >= ${D_FROM[$i]} and a < ${D_TO[$i]}"
143 vlog "Deleted rows for $i are in the range [${D_FROM[$i]}, ${D_TO[$i]}), total ${D_COUNT[$i]} are deleted"
144
145 #UPDATE
146 U_FROM[$i]=${D_TO[$i]}
147 U_TO[$i]=`$CLIENT_CMD "select max(a) from (select a from $TN where a >= ${U_FROM[$i]} limit 1000) as temp_table"`
148 U_COUNT[$i]=`$CLIENT_CMD "select count(*) from $TN where a>=${U_FROM[$i]} and a<${U_TO[$i]}"`
149 $CLIENT_CMD "update $TN set b=2 where a >= ${U_FROM[$i]} and a < ${U_TO[$i]}"
150 vlog "Updated rows for $i are in the range [${U_FROM[$i]}, ${U_TO[$i]}), total ${U_COUNT[$i]} are updated"
151
152 done
153}
154
155function get_changes
156{
157 local START_I=$1
158 local TABLES_COUNT=$2
159 local TABLE_NAME=$3
160 local CLIENT_CMD="${MYSQL} ${MYSQL_ARGS} -Ns test -e"
161
162 for i in `seq $START_I $(($START_I+$TABLES_COUNT-1))`; do
163 local TN=$TABLE_NAME$(($i-$START_I+1))
164
165 #INSERT
166 I_COUNT1[$i]=`$CLIENT_CMD "select count(*) from $TN where a >= ${I_FROM[$i]} and a < ${I_TO[$i]} "`
167 #DELETE
168 D_COUNT1[$i]=`$CLIENT_CMD "select count(*) from $TN where a >= ${D_FROM[$i]} and a < ${D_TO[$i]} "`
169 #UPDATE
170 U_COUNT1[$i]=`$CLIENT_CMD "select count(*) from $TN where a >= ${U_FROM[$i]} and a < ${U_TO[$i]} and b = 2"`
171 done
172}
173
174function check_changes
175{
176 local START_I=$1
177 local TABLES_COUNT=$2
178 local CMD=$3
179
180 for i in `seq $START_I $(($START_I+$TABLES_COUNT-1))`; do
181 $CMD "INSERT TEST for $i" ${I_COUNT[$i]} ${I_COUNT1[$i]}
182 $CMD "DELETE TEST for $i" 0 ${D_COUNT1[$i]}
183 $CMD "UPDATE TEST for $i" ${U_COUNT[$i]} ${U_COUNT1[$i]}
184 done
185}
186
187function unset_global_variables
188{
189 unset I_FROM
190 unset I_TO
191 unset I_COUNT
192
193 unset D_FROM
194 unset D_TO
195 unset D_COUNT
196
197 unset U_FROM
198 unset U_TO
199 unset U_COUNT
200
201 unset I_FROM1
202 unset I_TO1
203 unset I_COUNT1
204
205 unset D_FROM1
206 unset D_TO1
207 unset D_COUNT1
208
209 unset U_FROM1
210 unset U_TO1
211 unset U_COUNT1
212}
213
214function test_archived_logs
215{
216 local TABLE_NAME=T
217 local TABLES_COUNT=4
218 local EXTRA_OPTIONS=${1:-''}
219 local CREATE_TABLE_OPTIONS=${2:-''}
220
221 #Setup server environment to get access to some variables
222 init_server_variables 1
223 switch_server 1
224 local BASE_BACKUP_DIR=$topdir/backup_base
225 local BACKUP_DIR=$topdir/backup
226 local BASE_DATA_DIR=$topdir/base_data
227 local ARCHIVED_LOGS_DIR=$topdir/archived_logs
228 local XTRABACKUP_OPTIONS="--innodb_log_file_size=2M $EXTRA_OPTIONS"
229 #Setup ROW binlog format to supress warnings in result file
230 local SERVER_OPTIONS="$XTRABACKUP_OPTIONS --innodb_log_archive=ON --innodb_log_arch_dir=$ARCHIVED_LOGS_DIR --binlog-format=ROW"
231 mkdir -p $BASE_BACKUP_DIR $BACKUP_DIR
232 mkdir -p $ARCHIVED_LOGS_DIR
233 reset_server_variables 1
234
235 ###################################################################
236 # --to-lsn test. It checks the availability to apply logs only to #
237 # the certain LSN. #
238 ###################################################################
239 start_server $SERVER_OPTIONS
240 #Create and fill tables to generate log files
241 create_and_fill_db $TABLES_COUNT $TABLE_NAME $ARCHIVED_LOGS_DIR $CREATE_TABLE_OPTIONS
242 #Backup the data
243 xtrabackup --backup --datadir=$mysql_datadir --target-dir=$BASE_BACKUP_DIR $XTRABACKUP_OPTIONS
244 #Make some changes in tables after backup is done
245 make_changes 1 $TABLES_COUNT $TABLE_NAME
246 #Make sure that changes are flushed to archived log
247 repeat_until_new_arch_log_created \
248 $ARCHIVED_LOGS_DIR \
249 "fill_tables $TABLES_COUNT $TABLE_NAME"
250 #Remember current LSN
251 local LSN=`run_cmd $MYSQL $MYSQL_ARGS test -e 'SHOW ENGINE INNODB STATUS\G'|grep 'Log sequence number'|awk '{print $4}'`
252 #Make more changes over remembered LSN
253 make_changes $(($TABLES_COUNT+1)) $TABLES_COUNT $TABLE_NAME
254 #Make sure the above changes are flushed to archived log
255 repeat_until_new_arch_log_created \
256 $ARCHIVED_LOGS_DIR \
257 "fill_tables $TABLES_COUNT $TABLE_NAME"
258 stop_server
259 cp -R $mysql_datadir $BASE_DATA_DIR
260
261 #########################################
262 # Apply logs only to the remembered lsn #
263 #########################################
264 # --apply-logs-only is set implicitly because unfinished transactions
265 # can be finished on further logs applying but using this option with
266 # --innodb-log-arch-dir is tested here to prove this bug
267 # https://bugs.launchpad.net/percona-xtrabackup/+bug/1199555 is not
268 # concerned with this case
269 cp -R $BASE_BACKUP_DIR/* $BACKUP_DIR
270 xtrabackup --prepare \
271 --target-dir=$BACKUP_DIR \
272 --innodb-log-arch-dir=$ARCHIVED_LOGS_DIR \
273 --to-archived-lsn=$LSN \
274 --apply-logs-only \
275 $XTRABACKUP_OPTIONS
276 #Copy prepared data to server data dir
277 cp -R $BACKUP_DIR/* $mysql_datadir
278 rm $mysql_datadir/ib_*
279 #Start server with prepared data
280 start_server "--binlog-format=ROW $EXTRA_OPTIONS"
281 #Get values from restored data files before remembered LSN
282 get_changes 1 $TABLES_COUNT $TABLE_NAME
283 #Get values from restored data files after remembered LSN
284 get_changes $(($TABLES_COUNT+1)) $TABLES_COUNT $TABLE_NAME
285 #We don't need server already
286 stop_server
287 #Check if the changes which was made before remembered LSN are in the
288 #restored databse
289 check_changes 1 $TABLES_COUNT 'check_if_equal'
290 #Check if the changes which was made after remembered LSN are NOT in the
291 #restored databse
292 check_changes $(($TABLES_COUNT+1)) $TABLES_COUNT 'check_if_not_equal'
293 # Apply the rest of archived logs
294 xtrabackup --prepare \
295 --target-dir=$BACKUP_DIR \
296 --innodb-log-arch-dir=$ARCHIVED_LOGS_DIR \
297 --apply-logs-only \
298 $XTRABACKUP_OPTIONS
299 #Copy prepared data to server data dir
300 cp -R $BACKUP_DIR/* $mysql_datadir
301 rm $mysql_datadir/ib_*
302 #Start server with prepared data
303 start_server "--binlog-format=ROW $EXTRA_OPTIONS"
304 #Get values from restored data files before remembered LSN
305 get_changes 1 $TABLES_COUNT $TABLE_NAME
306 #Get values from restored data files after remembered LSN
307 get_changes $(($TABLES_COUNT+1)) $TABLES_COUNT $TABLE_NAME
308 stop_server
309 #Check if the changes which was made before remembered LSN are in the
310 #restored databse
311 check_changes 1 $TABLES_COUNT 'check_if_equal'
312 #Check if the changes which was made after remembered LSN are in the
313 #restored databse
314 check_changes $(($TABLES_COUNT+1)) $TABLES_COUNT 'check_if_equal'
315 rm -rf $mysql_datadir
316 rm -rf $BACKUP_DIR
317
318 ##################################################
319 # Check the possibility of applying logs by sets #
320 ##################################################
321 cp -R $BASE_DATA_DIR $mysql_datadir
322 cp -R $BASE_BACKUP_DIR $BACKUP_DIR
323 mkdir -p $ARCHIVED_LOGS_DIR/1 $ARCHIVED_LOGS_DIR/2
324 #Make two log files sets. The first set contains the first two files,
325 #the second set contains the rest and the last log file from the first
326 #set.
327 pushd .
328 cd $ARCHIVED_LOGS_DIR
329 for i in `find . -type f -printf "%T+ %p\n" | cut -d' ' -f2`;
330 do
331 local n=`echo $i | sed 's/.*ib_log_archive_\([0-9]*\).*/\1/'`;
332 if [ $n -le $LSN ];
333 then
334 mv $i 1/;
335 else
336 mv $i 2/;
337 fi;
338 done
339 cd 1
340 find . -type f -printf "%T+ %p\n" | cut -d' ' -f2 | sort -n | tail -1 | \
341 xargs -I{} cp {} ../2/
342 popd
343 #Prepare the first set
344 xtrabackup --prepare \
345 --target-dir=$BACKUP_DIR \
346 --innodb-log-arch-dir=$ARCHIVED_LOGS_DIR/1 \
347 $XTRABACKUP_OPTIONS
348 #Prepare the second set
349 xtrabackup --prepare \
350 --target-dir=$BACKUP_DIR \
351 --innodb-log-arch-dir=$ARCHIVED_LOGS_DIR/2 \
352 $XTRABACKUP_OPTIONS
353 #Copy prepared data to server data dir
354 cp -R $BACKUP_DIR/* $mysql_datadir
355 rm $mysql_datadir/ib_*
356 #Start server with prepared data
357 start_server "--binlog-format=ROW $EXTRA_OPTIONS"
358 #Get values from restored data files before remembered LSN
359 get_changes 1 $TABLES_COUNT $TABLE_NAME
360 #Get values from restored data files after remembered LSN
361 get_changes $(($TABLES_COUNT+1)) $TABLES_COUNT $TABLE_NAME
362 stop_server
363 #Check all made changes
364 check_changes 1 $TABLES_COUNT 'check_if_equal'
365 check_changes $(($TABLES_COUNT+1)) $TABLES_COUNT 'check_if_equal'
366
367 #Clean up dir for the next procedure launch
368 rm -rf $BACKUP_DIR/* $BASE_BACKUP_DIR/*
369 rm -rf $mysql_datadir $BASE_DATA_DIR
370 rm -rf $ARCHIVED_LOGS_DIR/*
371
372 #Clean up variables
373 unset_global_variables
374}
375
376require_xtradb
377require_server_version_higher_than '5.6.10'
378
379
380if [ `basename $XB_BIN` = 'xtrabackup_56' ]
381then
382 test_archived_logs
383 test_archived_logs '' 'ROW_FORMAT=COMPRESSED'
384else
385 echo 'Requires xtrabackup built with XtraDB >= 5.6' > $SKIPPED_REASON
386 exit $SKIPPED_EXIT_CODE
387fi
388
389exit $RESULT

Subscribers

People subscribed via source and target branches