A Lightweight SQL Database for Cloud Infrastructure and Web Applications

Merge lp:~stewart/drizzle/xtrabackup into lp:~drizzle-trunk/drizzle/development

Proposed by Stewart Smith on 2011-03-28
Status: Merged
Approved by: Stewart Smith on 2011-03-31
Approved revision: 2375
Merged at revision: 2259
Proposed branch: lp:~stewart/drizzle/xtrabackup
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 20356 lines (+19696/-13) 79 files modified
To merge this branch: bzr merge lp:~stewart/drizzle/xtrabackup
Reviewer Review Type Date Requested Status
Lee Bieber 2011-03-28 Needs Fixing on 2011-03-30
Review via email: mp+55241@code.launchpad.net

Description of the Change

xtrabackup port to drizzle. Produces a binary named 'drizzlebackup.innobase'

I've manually tested it a bit, but we now need to build more tests around it

To post a comment you must log in.
lp:~stewart/drizzle/xtrabackup updated on 2011-03-28
2369. By Stewart Smith on 2011-03-28

merge trunk

2370. By Stewart Smith on 2011-03-28

xtrabackup needs typedef for CHARSET_INFO, currently not changing everywhere inside xtrabackup for ease of merging from xtrabackup tree

Lee Bieber (kalebral) wrote :
review: Needs Fixing
lp:~stewart/drizzle/xtrabackup updated on 2011-03-30
2371. By Stewart Smith on 2011-03-30

merge trunk

2372. By Stewart Smith on 2011-03-30

definition of error::level_t has moved, fix xtrabackup build

Stewart Smith (stewart) wrote :

should be fixed now - a definition moved that we needed for the skeleton errmsg_printf()

lp:~stewart/drizzle/xtrabackup updated on 2011-03-31
2373. By Stewart Smith on 2011-03-31

since ibool is ulint, ICC gives us warnings in xtrabackup.cc when converting from ibool to bool.

2374. By Stewart Smith on 2011-03-31

merge latest xtrabackup from Percona tree

2375. By Stewart Smith on 2011-03-31

merge my patch to percona-xtrabackup for copyright headers

Stewart Smith (stewart) wrote :

should be ready again (ICC warnings and copyright header warnings fixed)

Preview Diff

1=== modified file 'plugin/innobase/btr/btr0btr.cc'
2--- plugin/innobase/btr/btr0btr.cc 2010-12-27 18:39:11 +0000
3+++ plugin/innobase/btr/btr0btr.cc 2011-03-31 06:44:38 +0000
4@@ -31,6 +31,7 @@
5
6 #include "fsp0fsp.h"
7 #include "page0page.h"
8+#include "xtrabackup_api.h"
9
10 #ifndef UNIV_HOTBACKUP
11 #include "btr0cur.h"
12@@ -120,7 +121,6 @@
13 /**************************************************************//**
14 Gets the root node of a tree and x-latches it.
15 @return root page, x-latched */
16-static
17 buf_block_t*
18 btr_root_block_get(
19 /*===============*/
20@@ -566,7 +566,6 @@
21 /************************************************************//**
22 Returns the child page of a node pointer and x-latches it.
23 @return child page, x-latched */
24-static
25 buf_block_t*
26 btr_node_ptr_get_child(
27 /*===================*/
28
29=== modified file 'plugin/innobase/buf/buf0buf.cc'
30--- plugin/innobase/buf/buf0buf.cc 2011-02-22 00:20:06 +0000
31+++ plugin/innobase/buf/buf0buf.cc 2011-03-31 06:44:38 +0000
32@@ -4053,7 +4053,7 @@
33 recv_recover_page(TRUE, (buf_block_t*) bpage);
34 }
35
36- if (uncompressed && !recv_no_ibuf_operations) {
37+ if (uncompressed && !recv_no_ibuf_operations && !srv_fake_write) {
38 ibuf_merge_or_delete_for_page(
39 (buf_block_t*) bpage, bpage->space,
40 bpage->offset, buf_page_get_zip_size(bpage),
41
42=== modified file 'plugin/innobase/fil/fil0fil.cc'
43--- plugin/innobase/fil/fil0fil.cc 2010-12-27 18:39:11 +0000
44+++ plugin/innobase/fil/fil0fil.cc 2011-03-31 06:44:38 +0000
45@@ -40,6 +40,7 @@
46 #include "dict0dict.h"
47 #include "page0page.h"
48 #include "page0zip.h"
49+#include "xtrabackup_api.h"
50 #ifndef UNIV_HOTBACKUP
51 # include "buf0lru.h"
52 # include "ibuf0ibuf.h"
53@@ -297,7 +298,7 @@
54
55 /** The tablespace memory cache. This variable is NULL before the module is
56 initialized. */
57-static fil_system_t* fil_system = NULL;
58+fil_system_t* fil_system = NULL;
59
60
61 /********************************************************************//**
62@@ -3448,7 +3449,6 @@
63 idea is to read as much good data as we can and jump over bad data.
64 @return 0 if ok, -1 if error even after the retries, 1 if at the end
65 of the directory */
66-static
67 int
68 fil_file_readdir_next_file(
69 /*=======================*/
70
71=== modified file 'plugin/innobase/ibuf/ibuf0ibuf.cc'
72--- plugin/innobase/ibuf/ibuf0ibuf.cc 2010-12-27 18:39:11 +0000
73+++ plugin/innobase/ibuf/ibuf0ibuf.cc 2011-03-31 06:44:38 +0000
74@@ -1125,6 +1125,9 @@
75
76 ut_ad(!recv_no_ibuf_operations);
77
78+ if (srv_fake_write)
79+ return(FALSE);
80+
81 if (ibuf_fixed_addr_page(space, zip_size, page_no)) {
82
83 return(TRUE);
84@@ -2613,6 +2616,9 @@
85 ulint n_bytes;
86 ulint n_pag2;
87
88+ if (srv_fake_write)
89+ return(0);
90+
91 while (sum_pages < n_pages) {
92 n_bytes = ibuf_contract_ext(&n_pag2, sync);
93
94
95=== modified file 'plugin/innobase/include/srv0srv.h'
96--- plugin/innobase/include/srv0srv.h 2011-03-14 05:40:28 +0000
97+++ plugin/innobase/include/srv0srv.h 2011-03-31 06:44:38 +0000
98@@ -222,6 +222,11 @@
99 extern ulong srv_max_purge_lag;
100
101 extern ulong srv_replication_delay;
102+
103+extern ibool srv_read_only;
104+extern ibool srv_fake_write;
105+extern ibool srv_apply_log_only;
106+
107 /*-------------------------------------------*/
108
109 extern ulint srv_n_rows_inserted;
110
111=== added file 'plugin/innobase/include/xtrabackup_api.h'
112--- plugin/innobase/include/xtrabackup_api.h 1970-01-01 00:00:00 +0000
113+++ plugin/innobase/include/xtrabackup_api.h 2011-03-31 06:44:38 +0000
114@@ -0,0 +1,87 @@
115+/*****************************************************************************
116+
117+Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
118+Copyright (C) 2011 Stewart Smith
119+
120+This program is free software; you can redistribute it and/or modify it under
121+the terms of the GNU General Public License as published by the Free Software
122+Foundation; version 2 of the License.
123+
124+This program is distributed in the hope that it will be useful, but WITHOUT
125+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
126+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
127+
128+You should have received a copy of the GNU General Public License along with
129+this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
130+St, Fifth Floor, Boston, MA 02110-1301 USA
131+
132+*****************************************************************************/
133+
134+/* this file is the internal functions that are used by xtrabackup.
135+ They probably shouldn't be called anywhere else.
136+ */
137+
138+#pragma once
139+
140+ulint
141+recv_find_max_checkpoint(log_group_t** max_group,
142+ ulint* max_field);
143+
144+ibool
145+log_block_checksum_is_ok_or_old_format(const byte* block);
146+
147+ulint
148+open_or_create_data_files(ibool* create_new_db,
149+#ifdef UNIV_LOG_ARCHIVE
150+ ulint* min_arch_log_no,/*!< out: min of archived log
151+ numbers in data files */
152+ ulint* max_arch_log_no,/*!< out: max of archived log
153+ numbers in data files */
154+#endif /* UNIV_LOG_ARCHIVE */
155+ ib_uint64_t* min_flushed_lsn,/*!< out: min of flushed lsn
156+ values in data files */
157+ ib_uint64_t* max_flushed_lsn,/*!< out: max of flushed lsn
158+ values in data files */
159+ ulint* sum_of_new_sizes);/*!< out: sum of sizes of the
160+ new files added */
161+
162+ulint
163+open_or_create_log_file(
164+/*====================*/
165+ ibool create_new_db, /*!< in: TRUE if we should create a
166+ new database */
167+ ibool* log_file_created, /*!< out: TRUE if new log file
168+ created */
169+ ibool log_file_has_been_opened,/*!< in: TRUE if a log file has been
170+ opened before: then it is an error
171+ to try to create another log file */
172+ ulint k, /*!< in: log group number */
173+ ulint i); /*!< in: log file number in group */
174+
175+buf_block_t*
176+btr_root_block_get(
177+/*===============*/
178+ dict_index_t* index, /*!< in: index tree */
179+ mtr_t* mtr); /*!< in: mtr */
180+
181+buf_block_t*
182+btr_node_ptr_get_child(
183+/*===================*/
184+ const rec_t* node_ptr,/*!< in: node pointer */
185+ dict_index_t* index, /*!< in: index */
186+ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
187+ mtr_t* mtr); /*!< in: mtr */
188+
189+ibool
190+recv_check_cp_is_consistent(
191+/*========================*/
192+ const byte* buf); /*!< in: buffer containing checkpoint info */
193+
194+int
195+fil_file_readdir_next_file(
196+/*=======================*/
197+ ulint* err, /*!< out: this is set to DB_ERROR if an error
198+ was encountered, otherwise not changed */
199+ const char* dirname,/*!< in: directory name or path */
200+ os_file_dir_t dir, /*!< in: directory stream */
201+ os_file_stat_t* info); /*!< in/out: buffer where the info is returned */
202
203=== modified file 'plugin/innobase/log/log0log.cc'
204--- plugin/innobase/log/log0log.cc 2011-02-22 00:20:06 +0000
205+++ plugin/innobase/log/log0log.cc 2011-03-31 06:44:38 +0000
206@@ -1356,7 +1356,7 @@
207 #endif /* UNIV_DEBUG */
208 ulint unlock;
209
210- if (recv_no_ibuf_operations) {
211+ if (recv_no_ibuf_operations || srv_fake_write) {
212 /* Recovery is running and no operations on the log files are
213 allowed yet (the variable name .._no_ibuf_.. is misleading) */
214
215@@ -3116,6 +3116,7 @@
216 for the 'very fast' shutdown, because the InnoDB layer may have
217 committed or prepared transactions and we don't want to lose them. */
218
219+ if (! srv_apply_log_only) {
220 if (trx_n_mysql_transactions > 0
221 || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
222
223@@ -3123,6 +3124,7 @@
224
225 goto loop;
226 }
227+ }
228
229 if (srv_fast_shutdown == 2) {
230 /* In this fastest shutdown we do not flush the buffer pool:
231
232=== modified file 'plugin/innobase/log/log0recv.cc'
233--- plugin/innobase/log/log0recv.cc 2011-02-22 00:20:06 +0000
234+++ plugin/innobase/log/log0recv.cc 2011-03-31 06:44:38 +0000
235@@ -42,6 +42,7 @@
236 #include "trx0undo.h"
237 #include "trx0rec.h"
238 #include "fil0fil.h"
239+#include "xtrabackup_api.h"
240 #ifndef UNIV_HOTBACKUP
241 # include "buf0rea.h"
242 # include "srv0srv.h"
243@@ -623,7 +624,6 @@
244 /***********************************************************************//**
245 Checks the consistency of the checkpoint info
246 @return TRUE if ok */
247-static
248 ibool
249 recv_check_cp_is_consistent(
250 /*========================*/
251@@ -653,7 +653,6 @@
252 /********************************************************//**
253 Looks for the maximum consistent checkpoint from the log groups.
254 @return error code or DB_SUCCESS */
255-static
256 ulint
257 recv_find_max_checkpoint(
258 /*=====================*/
259@@ -822,7 +821,6 @@
260 InnoDB-3.23.52 where the checksum field contains the log block number.
261 @return TRUE if ok, or if the log block may be in the format of InnoDB
262 version predating 3.23.52 */
263-static
264 ibool
265 log_block_checksum_is_ok_or_old_format(
266 /*===================================*/
267@@ -3260,6 +3258,7 @@
268 that the data dictionary tables will be free of any locks.
269 The data dictionary latch should guarantee that there is at
270 most one data dictionary transaction active at a time. */
271+ if (! srv_apply_log_only)
272 trx_rollback_or_clean_recovered(FALSE);
273 }
274
275
276=== modified file 'plugin/innobase/os/os0file.cc'
277--- plugin/innobase/os/os0file.cc 2011-02-07 09:18:43 +0000
278+++ plugin/innobase/os/os0file.cc 2011-03-31 06:44:38 +0000
279@@ -652,6 +652,10 @@
280 const char* name) /*!< in: file name */
281 {
282 struct flock lk;
283+
284+ if (srv_read_only)
285+ return 0;
286+
287 lk.l_type = F_WRLCK;
288 lk.l_whence = SEEK_SET;
289 lk.l_start = lk.l_len = 0;
290@@ -1495,7 +1499,10 @@
291 if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW
292 || create_mode == OS_FILE_OPEN_RETRY) {
293 mode_str = "OPEN";
294- create_flag = O_RDWR;
295+ if (srv_read_only)
296+ create_flag = O_RDONLY;
297+ else
298+ create_flag = O_RDWR;
299 } else if (create_mode == OS_FILE_CREATE) {
300 mode_str = "CREATE";
301 create_flag = O_RDWR | O_CREAT | O_EXCL;
302@@ -2291,6 +2298,9 @@
303 }
304 }
305
306+ if (srv_fake_write)
307+ return(TRUE);
308+
309 os_n_file_writes++;
310
311 #if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
312@@ -2673,6 +2683,9 @@
313 ut_a((offset & 0xFFFFFFFFUL) == offset);
314 ut_a((n & 0xFFFFFFFFUL) == n);
315
316+ if (srv_fake_write)
317+ return(TRUE);
318+
319 os_n_file_writes++;
320
321 ut_ad(file);
322
323=== modified file 'plugin/innobase/plugin.am'
324--- plugin/innobase/plugin.am 2011-02-04 22:30:00 +0000
325+++ plugin/innobase/plugin.am 2011-03-31 06:44:38 +0000
326@@ -1,4 +1,4 @@
327-# vim:ft=automake
328+ vim:ft=automake
329 # Copyright (C) 2001, 2004, 2006 MySQL AB & Innobase Oy
330 # Copyright (C) 2010 Brian Aker, Joe Daly, Monty Taylor
331 #
332@@ -209,6 +209,7 @@
333 plugin/innobase/include/ut0wqueue.h \
334 plugin/innobase/include/ha_prototypes.h \
335 plugin/innobase/include/handler0alter.h \
336+ plugin/innobase/include/xtrabackup_api.h \
337 plugin/innobase/mem/mem0dbg.cc \
338 plugin/innobase/handler/ha_innodb.h \
339 plugin/innobase/handler/handler0vars.h \
340@@ -222,8 +223,20 @@
341 noinst_LTLIBRARIES+= \
342 plugin/innobase/libinnobase.la \
343 plugin/innobase/libpars.la
344+bin_PROGRAMS+= plugin/innobase/xtrabackup/drizzlebackup.innobase
345 endif
346
347+plugin_innobase_xtrabackup_drizzlebackup_innobase_SOURCES = plugin/innobase/xtrabackup/xtrabackup.cc
348+plugin_innobase_xtrabackup_drizzlebackup_innobase_LDADD = \
349+ plugin/innobase/libinnobase.la \
350+ drizzled/internal/libinternal.la \
351+ drizzled/libcharset.la \
352+ $(BOOST_LIBS) \
353+ ${LTLIBAIO} \
354+ $(LIBZ)
355+
356+plugin_innobase_xtrabackup_drizzlebackup_innobase_CXXFLAGS=${AM_CXXFLAGS} ${INNOBASE_SKIP_WARNINGS} -I${top_builddir}/plugin/innobase/include -I$(top_srcdir)/plugin/innobase/include -DBUILD_DRIZZLE
357+
358 plugin_innobase_libinnobase_la_CXXFLAGS=${AM_CXXFLAGS} ${INNOBASE_SKIP_WARNINGS} -I${top_builddir}/plugin/innobase/include -I$(top_srcdir)/plugin/innobase/include -DBUILD_DRIZZLE
359 plugin_innobase_libinnobase_la_LDDADD= ${LTLIBAIO}
360 plugin_innobase_libinnobase_la_SOURCES= \
361
362=== modified file 'plugin/innobase/srv/srv0srv.cc'
363--- plugin/innobase/srv/srv0srv.cc 2011-02-22 00:20:06 +0000
364+++ plugin/innobase/srv/srv0srv.cc 2011-03-31 06:44:38 +0000
365@@ -433,6 +433,10 @@
366
367 UNIV_INTERN ulong srv_replication_delay = 0;
368
369+UNIV_INTERN ibool srv_read_only = FALSE;
370+UNIV_INTERN ibool srv_fake_write = FALSE;
371+UNIV_INTERN ibool srv_apply_log_only = FALSE;
372+
373 /*-------------------------------------------*/
374 UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
375 UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
376
377=== modified file 'plugin/innobase/srv/srv0start.cc'
378--- plugin/innobase/srv/srv0start.cc 2011-02-22 00:20:06 +0000
379+++ plugin/innobase/srv/srv0start.cc 2011-03-31 06:44:38 +0000
380@@ -88,6 +88,7 @@
381 # include "thr0loc.h"
382 # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
383 # include "zlib.h" /* for ZLIB_VERSION */
384+#include "xtrabackup_api.h"
385
386 #include <errno.h>
387 #include <unistd.h>
388@@ -555,7 +556,6 @@
389 /*********************************************************************//**
390 Creates or opens the log files and closes them.
391 @return DB_SUCCESS or error code */
392-static
393 ulint
394 open_or_create_log_file(
395 /*====================*/
396@@ -708,7 +708,6 @@
397 /*********************************************************************//**
398 Creates or opens database data files and closes them.
399 @return DB_SUCCESS or error code */
400-static
401 ulint
402 open_or_create_data_files(
403 /*======================*/
404@@ -1558,6 +1557,10 @@
405 are initialized in trx_sys_init_at_db_start(). */
406
407 recv_recovery_from_checkpoint_finish();
408+
409+ if (srv_apply_log_only)
410+ goto skip_processes;
411+
412 if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) {
413 /* The following call is necessary for the insert
414 buffer to work with multiple tablespaces. We must
415@@ -1824,6 +1827,7 @@
416 ibuf_update_max_tablespace_id();
417 }
418
419+skip_processes:
420 srv_file_per_table = srv_file_per_table_original_value;
421
422 srv_was_started = TRUE;
423
424=== modified file 'plugin/innobase/trx/trx0purge.cc'
425--- plugin/innobase/trx/trx0purge.cc 2010-12-26 21:16:41 +0000
426+++ plugin/innobase/trx/trx0purge.cc 2011-03-31 06:44:38 +0000
427@@ -1100,6 +1100,9 @@
428 /* que_thr_t* thr2; */
429 ulint old_pages_handled;
430
431+ if (srv_fake_write)
432+ return(0);
433+
434 mutex_enter(&(purge_sys->mutex));
435
436 if (purge_sys->trx->n_active_thrs > 0) {
437
438=== modified file 'plugin/innobase/trx/trx0rseg.cc'
439--- plugin/innobase/trx/trx0rseg.cc 2010-12-26 21:25:00 +0000
440+++ plugin/innobase/trx/trx0rseg.cc 2011-03-31 06:44:38 +0000
441@@ -140,9 +140,11 @@
442
443 mutex_free(&rseg->mutex);
444
445+ if (! srv_apply_log_only) {
446 /* There can't be any active transactions. */
447 ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0);
448 ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0);
449+ }
450
451 undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);
452
453
454=== modified file 'plugin/innobase/trx/trx0sys.cc'
455--- plugin/innobase/trx/trx0sys.cc 2011-02-22 00:20:06 +0000
456+++ plugin/innobase/trx/trx0sys.cc 2011-03-31 06:44:38 +0000
457@@ -1476,10 +1476,12 @@
458 UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view);
459 }
460
461+ if (! srv_apply_log_only) {
462 ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0);
463 ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0);
464 ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0);
465 ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
466+ }
467
468 mem_free(trx_sys);
469
470
471=== added directory 'plugin/innobase/xtrabackup'
472=== added file 'plugin/innobase/xtrabackup/BUILD.txt'
473--- plugin/innobase/xtrabackup/BUILD.txt 1970-01-01 00:00:00 +0000
474+++ plugin/innobase/xtrabackup/BUILD.txt 2011-03-31 06:44:38 +0000
475@@ -0,0 +1,21 @@
476+How to build XtraBackup
477+=======================
478+
479+!!You need to build the MySQL binaries before building XtraBackup!!
480+
481+1. Build your version of mysql
482+
483+2. copy the xtrabackup source directory into the mysql.5x/innobase directory
484+ (e.g. mysql-5.0.75/innobase/xtrabackup-0.0 )
485+
486+3. For 5.1x you need to apply a patch.
487+ From the innobase directory, apply the xtrabackup patch.
488+ e.g. #patch -p2 < xtrabackup-0.0/fix_innodb_for_backup51.patch
489+
490+(With 5.0 run 'make clean all' from the innobase directory This is necessary
491+for 5.0, because of the lack of dependencies)
492+
493+4.Run make [5.0] [5.1] [xtradb] [plugin] in the XtraBackup directory.
494+
495+5. enjoy... :
496+
497
498=== added file 'plugin/innobase/xtrabackup/COPYING'
499--- plugin/innobase/xtrabackup/COPYING 1970-01-01 00:00:00 +0000
500+++ plugin/innobase/xtrabackup/COPYING 2011-03-31 06:44:38 +0000
501@@ -0,0 +1,351 @@
502+ GNU GENERAL PUBLIC LICENSE
503+ Version 2, June 1991
504+
505+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
506+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
507+
508+ Everyone is permitted to copy and distribute verbatim copies
509+ of this license document, but changing it is not allowed.
510+
511+Preamble
512+========
513+
514+The licenses for most software are designed to take away your freedom
515+to share and change it. By contrast, the GNU General Public License is
516+intended to guarantee your freedom to share and change free
517+software--to make sure the software is free for all its users. This
518+General Public License applies to most of the Free Software
519+Foundation's software and to any other program whose authors commit to
520+using it. (Some other Free Software Foundation software is covered by
521+the GNU Library General Public License instead.) You can apply it to
522+your programs, too.
523+
524+When we speak of free software, we are referring to freedom, not price.
525+Our General Public Licenses are designed to make sure that you have
526+the freedom to distribute copies of free software (and charge for this
527+service if you wish), that you receive source code or can get it if you
528+want it, that you can change the software or use pieces of it in new
529+free programs; and that you know you can do these things.
530+
531+To protect your rights, we need to make restrictions that forbid anyone
532+to deny you these rights or to ask you to surrender the rights. These
533+restrictions translate to certain responsibilities for you if you
534+distribute copies of the software, or if you modify it.
535+
536+For example, if you distribute copies of such a program, whether gratis
537+or for a fee, you must give the recipients all the rights that you
538+have. You must make sure that they, too, receive or can get the source
539+code. And you must show them these terms so they know their rights.
540+
541+We protect your rights with two steps: (1) copyright the software, and
542+(2) offer you this license which gives you legal permission to copy,
543+distribute and/or modify the software.
544+
545+Also, for each author's protection and ours, we want to make certain
546+that everyone understands that there is no warranty for this free
547+software. If the software is modified by someone else and passed on, we
548+want its recipients to know that what they have is not the original, so
549+that any problems introduced by others will not reflect on the original
550+authors' reputations.
551+
552+Finally, any free program is threatened constantly by software patents.
553+We wish to avoid the danger that redistributors of a free program will
554+individually obtain patent licenses, in effect making the program
555+proprietary. To prevent this, we have made it clear that any patent
556+must be licensed for everyone's free use or not licensed at all.
557+
558+The precise terms and conditions for copying, distribution and
559+modification follow.
560+
561+ GNU GENERAL PUBLIC LICENSE
562+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
563+ 0. This License applies to any program or other work which contains a
564+ notice placed by the copyright holder saying it may be distributed
565+ under the terms of this General Public License. The "Program",
566+ below, refers to any such program or work, and a "work based on
567+ the Program" means either the Program or any derivative work under
568+ copyright law: that is to say, a work containing the Program or a
569+ portion of it, either verbatim or with modifications and/or
570+ translated into another language. (Hereinafter, translation is
571+ included without limitation in the term "modification".) Each
572+ licensee is addressed as "you".
573+
574+ Activities other than copying, distribution and modification are
575+ not covered by this License; they are outside its scope. The act
576+ of running the Program is not restricted, and the output from the
577+ Program is covered only if its contents constitute a work based on
578+ the Program (independent of having been made by running the
579+ Program). Whether that is true depends on what the Program does.
580+
581+ 1. You may copy and distribute verbatim copies of the Program's
582+ source code as you receive it, in any medium, provided that you
583+ conspicuously and appropriately publish on each copy an appropriate
584+ copyright notice and disclaimer of warranty; keep intact all the
585+ notices that refer to this License and to the absence of any
586+ warranty; and give any other recipients of the Program a copy of
587+ this License along with the Program.
588+
589+ You may charge a fee for the physical act of transferring a copy,
590+ and you may at your option offer warranty protection in exchange
591+ for a fee.
592+
593+ 2. You may modify your copy or copies of the Program or any portion
594+ of it, thus forming a work based on the Program, and copy and
595+ distribute such modifications or work under the terms of Section 1
596+ above, provided that you also meet all of these conditions:
597+
598+ a. You must cause the modified files to carry prominent notices
599+ stating that you changed the files and the date of any change.
600+
601+ b. You must cause any work that you distribute or publish, that
602+ in whole or in part contains or is derived from the Program
603+ or any part thereof, to be licensed as a whole at no charge
604+ to all third parties under the terms of this License.
605+
606+ c. If the modified program normally reads commands interactively
607+ when run, you must cause it, when started running for such
608+ interactive use in the most ordinary way, to print or display
609+ an announcement including an appropriate copyright notice and
610+ a notice that there is no warranty (or else, saying that you
611+ provide a warranty) and that users may redistribute the
612+ program under these conditions, and telling the user how to
613+ view a copy of this License. (Exception: if the Program
614+ itself is interactive but does not normally print such an
615+ announcement, your work based on the Program is not required
616+ to print an announcement.)
617+
618+ These requirements apply to the modified work as a whole. If
619+ identifiable sections of that work are not derived from the
620+ Program, and can be reasonably considered independent and separate
621+ works in themselves, then this License, and its terms, do not
622+ apply to those sections when you distribute them as separate
623+ works. But when you distribute the same sections as part of a
624+ whole which is a work based on the Program, the distribution of
625+ the whole must be on the terms of this License, whose permissions
626+ for other licensees extend to the entire whole, and thus to each
627+ and every part regardless of who wrote it.
628+
629+ Thus, it is not the intent of this section to claim rights or
630+ contest your rights to work written entirely by you; rather, the
631+ intent is to exercise the right to control the distribution of
632+ derivative or collective works based on the Program.
633+
634+ In addition, mere aggregation of another work not based on the
635+ Program with the Program (or with a work based on the Program) on
636+ a volume of a storage or distribution medium does not bring the
637+ other work under the scope of this License.
638+
639+ 3. You may copy and distribute the Program (or a work based on it,
640+ under Section 2) in object code or executable form under the terms
641+ of Sections 1 and 2 above provided that you also do one of the
642+ following:
643+
644+ a. Accompany it with the complete corresponding machine-readable
645+ source code, which must be distributed under the terms of
646+ Sections 1 and 2 above on a medium customarily used for
647+ software interchange; or,
648+
649+ b. Accompany it with a written offer, valid for at least three
650+ years, to give any third-party, for a charge no more than your
651+ cost of physically performing source distribution, a complete
652+ machine-readable copy of the corresponding source code, to be
653+ distributed under the terms of Sections 1 and 2 above on a
654+ medium customarily used for software interchange; or,
655+
656+ c. Accompany it with the information you received as to the offer
657+ to distribute corresponding source code. (This alternative is
658+ allowed only for noncommercial distribution and only if you
659+ received the program in object code or executable form with
660+ such an offer, in accord with Subsection b above.)
661+
662+ The source code for a work means the preferred form of the work for
663+ making modifications to it. For an executable work, complete
664+ source code means all the source code for all modules it contains,
665+ plus any associated interface definition files, plus the scripts
666+ used to control compilation and installation of the executable.
667+ However, as a special exception, the source code distributed need
668+ not include anything that is normally distributed (in either
669+ source or binary form) with the major components (compiler,
670+ kernel, and so on) of the operating system on which the executable
671+ runs, unless that component itself accompanies the executable.
672+
673+ If distribution of executable or object code is made by offering
674+ access to copy from a designated place, then offering equivalent
675+ access to copy the source code from the same place counts as
676+ distribution of the source code, even though third parties are not
677+ compelled to copy the source along with the object code.
678+
679+ 4. You may not copy, modify, sublicense, or distribute the Program
680+ except as expressly provided under this License. Any attempt
681+ otherwise to copy, modify, sublicense or distribute the Program is
682+ void, and will automatically terminate your rights under this
683+ License. However, parties who have received copies, or rights,
684+ from you under this License will not have their licenses
685+ terminated so long as such parties remain in full compliance.
686+
687+ 5. You are not required to accept this License, since you have not
688+ signed it. However, nothing else grants you permission to modify
689+ or distribute the Program or its derivative works. These actions
690+ are prohibited by law if you do not accept this License.
691+ Therefore, by modifying or distributing the Program (or any work
692+ based on the Program), you indicate your acceptance of this
693+ License to do so, and all its terms and conditions for copying,
694+ distributing or modifying the Program or works based on it.
695+
696+ 6. Each time you redistribute the Program (or any work based on the
697+ Program), the recipient automatically receives a license from the
698+ original licensor to copy, distribute or modify the Program
699+ subject to these terms and conditions. You may not impose any
700+ further restrictions on the recipients' exercise of the rights
701+ granted herein. You are not responsible for enforcing compliance
702+ by third parties to this License.
703+
704+ 7. If, as a consequence of a court judgment or allegation of patent
705+ infringement or for any other reason (not limited to patent
706+ issues), conditions are imposed on you (whether by court order,
707+ agreement or otherwise) that contradict the conditions of this
708+ License, they do not excuse you from the conditions of this
709+ License. If you cannot distribute so as to satisfy simultaneously
710+ your obligations under this License and any other pertinent
711+ obligations, then as a consequence you may not distribute the
712+ Program at all. For example, if a patent license would not permit
713+ royalty-free redistribution of the Program by all those who
714+ receive copies directly or indirectly through you, then the only
715+ way you could satisfy both it and this License would be to refrain
716+ entirely from distribution of the Program.
717+
718+ If any portion of this section is held invalid or unenforceable
719+ under any particular circumstance, the balance of the section is
720+ intended to apply and the section as a whole is intended to apply
721+ in other circumstances.
722+
723+ It is not the purpose of this section to induce you to infringe any
724+ patents or other property right claims or to contest validity of
725+ any such claims; this section has the sole purpose of protecting
726+ the integrity of the free software distribution system, which is
727+ implemented by public license practices. Many people have made
728+ generous contributions to the wide range of software distributed
729+ through that system in reliance on consistent application of that
730+ system; it is up to the author/donor to decide if he or she is
731+ willing to distribute software through any other system and a
732+ licensee cannot impose that choice.
733+
734+ This section is intended to make thoroughly clear what is believed
735+ to be a consequence of the rest of this License.
736+
737+ 8. If the distribution and/or use of the Program is restricted in
738+ certain countries either by patents or by copyrighted interfaces,
739+ the original copyright holder who places the Program under this
740+ License may add an explicit geographical distribution limitation
741+ excluding those countries, so that distribution is permitted only
742+ in or among countries not thus excluded. In such case, this
743+ License incorporates the limitation as if written in the body of
744+ this License.
745+
746+ 9. The Free Software Foundation may publish revised and/or new
747+ versions of the General Public License from time to time. Such
748+ new versions will be similar in spirit to the present version, but
749+ may differ in detail to address new problems or concerns.
750+
751+ Each version is given a distinguishing version number. If the
752+ Program specifies a version number of this License which applies
753+ to it and "any later version", you have the option of following
754+ the terms and conditions either of that version or of any later
755+ version published by the Free Software Foundation. If the Program
756+ does not specify a version number of this License, you may choose
757+ any version ever published by the Free Software Foundation.
758+
759+ 10. If you wish to incorporate parts of the Program into other free
760+ programs whose distribution conditions are different, write to the
761+ author to ask for permission. For software which is copyrighted
762+ by the Free Software Foundation, write to the Free Software
763+ Foundation; we sometimes make exceptions for this. Our decision
764+ will be guided by the two goals of preserving the free status of
765+ all derivatives of our free software and of promoting the sharing
766+ and reuse of software generally.
767+
768+ NO WARRANTY
769+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
770+ WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
771+ LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
772+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
773+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
774+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
775+ FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
776+ QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
777+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
778+ SERVICING, REPAIR OR CORRECTION.
779+
780+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
781+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
782+ MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
783+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
784+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
785+ INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
786+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
787+ OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
788+ OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
789+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
790+
791+ END OF TERMS AND CONDITIONS
792+How to Apply These Terms to Your New Programs
793+=============================================
794+
795+If you develop a new program, and you want it to be of the greatest
796+possible use to the public, the best way to achieve this is to make it
797+free software which everyone can redistribute and change under these
798+terms.
799+
800+To do so, attach the following notices to the program. It is safest to
801+attach them to the start of each source file to most effectively convey
802+the exclusion of warranty; and each file should have at least the
803+"copyright" line and a pointer to where the full notice is found.
804+
805+ ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
806+ Copyright (C) YYYY NAME OF AUTHOR
807+
808+ This program is free software; you can redistribute it and/or modify
809+ it under the terms of the GNU General Public License as published by
810+ the Free Software Foundation; either version 2 of the License, or
811+ (at your option) any later version.
812+
813+ This program is distributed in the hope that it will be useful,
814+ but WITHOUT ANY WARRANTY; without even the implied warranty of
815+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
816+ GNU General Public License for more details.
817+
818+ You should have received a copy of the GNU General Public License
819+ along with this program; if not, write to the Free Software
820+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
821+
822+Also add information on how to contact you by electronic and paper mail.
823+
824+If the program is interactive, make it output a short notice like this
825+when it starts in an interactive mode:
826+
827+ Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR
828+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
829+ This is free software, and you are welcome to redistribute it
830+ under certain conditions; type `show c' for details.
831+
832+The hypothetical commands `show w' and `show c' should show the
833+appropriate parts of the General Public License. Of course, the
834+commands you use may be called something other than `show w' and `show
835+c'; they could even be mouse-clicks or menu items--whatever suits your
836+program.
837+
838+You should also get your employer (if you work as a programmer) or your
839+school, if any, to sign a "copyright disclaimer" for the program, if
840+necessary. Here is a sample; alter the names:
841+
842+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
843+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
844+
845+ SIGNATURE OF TY COON, 1 April 1989
846+ Ty Coon, President of Vice
847+
848+This General Public License does not permit incorporating your program
849+into proprietary programs. If your program is a subroutine library,
850+you may consider it more useful to permit linking proprietary
851+applications with the library. If this is what you want to do, use the
852+GNU Library General Public License instead of this License.
853
854=== added file 'plugin/innobase/xtrabackup/Makefile'
855--- plugin/innobase/xtrabackup/Makefile 1970-01-01 00:00:00 +0000
856+++ plugin/innobase/xtrabackup/Makefile 2011-03-31 06:44:38 +0000
857@@ -0,0 +1,141 @@
858+# Makefile to build XtraBackup for Percona Server and different versions of MySQL
859+#
860+# Syntax:
861+# make [5.1|5.5|xtradb|xtradb55]
862+#
863+# Default is xtradb - to build XtraBackup for Percona Server 5.1
864+# xtradb55 - Xtrabackup for Percona Server 5.5
865+# 5.1 - XtraBackup for MySQL versions 5.1.* with builtin InnoDB
866+# 5.5 - XtraBackup for MySQL versions 5.5.*
867+
868+LIBS = -lpthread
869+DEFS = -DUNIV_LINUX -DMYSQL_SERVER
870+
871+CFLAGS += -O3 -g -pedantic -Wall -Wundef -Wshadow -fdiagnostics-show-option -fno-strict-aliasing -Wno-strict-aliasing -Wextra -Wformat -Wno-format-nonliteral -Wno-format-security -Wno-long-long -Wmissing-declarations -Wno-redundant-decls --std=gnu99
872+
873+TARGET=xtrabackup
874+PREFIX=/usr
875+BIN_DIR=$(PREFIX)/bin
876+
877+default: xtradb
878+
879+# XtraBackup for MySQL 5.1
880+5.1: INC = -I. -isystem.. -isystem./../include -isystem./../../include -isystem./../../../include
881+5.1: INNODBOBJS = ../libinnobase_a-btr0btr.o ../libinnobase_a-btr0cur.o ../libinnobase_a-btr0pcur.o \
882+ ../libinnobase_a-btr0sea.o ../libinnobase_a-buf0buf.o ../libinnobase_a-buf0flu.o \
883+ ../libinnobase_a-buf0lru.o ../libinnobase_a-buf0rea.o ../libinnobase_a-data0data.o \
884+ ../libinnobase_a-data0type.o ../libinnobase_a-dict0boot.o ../libinnobase_a-dict0crea.o \
885+ ../libinnobase_a-dict0dict.o ../libinnobase_a-dict0load.o ../libinnobase_a-dict0mem.o \
886+ ../libinnobase_a-dyn0dyn.o ../libinnobase_a-eval0eval.o ../libinnobase_a-eval0proc.o \
887+ ../libinnobase_a-fil0fil.o ../libinnobase_a-fsp0fsp.o ../libinnobase_a-fut0fut.o \
888+ ../libinnobase_a-fut0lst.o ../libinnobase_a-ha0ha.o ../libinnobase_a-hash0hash.o \
889+ ../libinnobase_a-ibuf0ibuf.o ../libinnobase_a-lock0iter.o ../libinnobase_a-lock0lock.o \
890+ ../libinnobase_a-log0log.o ../libinnobase_a-log0recv.o ../libinnobase_a-mach0data.o \
891+ ../libinnobase_a-mem0mem.o ../libinnobase_a-mem0pool.o ../libinnobase_a-mtr0log.o \
892+ ../libinnobase_a-mtr0mtr.o ../libinnobase_a-os0file.o ../libinnobase_a-os0proc.o \
893+ ../libinnobase_a-os0sync.o ../libinnobase_a-os0thread.o ../libinnobase_a-page0cur.o \
894+ ../libinnobase_a-page0page.o ../libinnobase_a-lexyy.o ../libinnobase_a-pars0grm.o \
895+ ../libinnobase_a-pars0opt.o ../libinnobase_a-pars0pars.o ../libinnobase_a-pars0sym.o \
896+ ../libinnobase_a-que0que.o ../libinnobase_a-read0read.o ../libinnobase_a-rem0cmp.o \
897+ ../libinnobase_a-rem0rec.o ../libinnobase_a-row0ins.o ../libinnobase_a-row0mysql.o \
898+ ../libinnobase_a-row0purge.o ../libinnobase_a-row0row.o ../libinnobase_a-row0sel.o \
899+ ../libinnobase_a-row0uins.o ../libinnobase_a-row0umod.o ../libinnobase_a-row0undo.o \
900+ ../libinnobase_a-row0upd.o ../libinnobase_a-row0vers.o ../libinnobase_a-srv0que.o \
901+ ../libinnobase_a-srv0srv.o ../libinnobase_a-srv0start.o ../libinnobase_a-sync0arr.o \
902+ ../libinnobase_a-sync0rw.o ../libinnobase_a-sync0sync.o ../libinnobase_a-thr0loc.o \
903+ ../libinnobase_a-trx0purge.o ../libinnobase_a-trx0rec.o ../libinnobase_a-trx0roll.o \
904+ ../libinnobase_a-trx0rseg.o ../libinnobase_a-trx0sys.o ../libinnobase_a-trx0trx.o \
905+ ../libinnobase_a-trx0undo.o ../libinnobase_a-usr0sess.o ../libinnobase_a-ut0byte.o \
906+ ../libinnobase_a-ut0dbg.o ../libinnobase_a-ut0list.o ../libinnobase_a-ut0mem.o \
907+ ../libinnobase_a-ut0rnd.o ../libinnobase_a-ut0ut.o ../libinnobase_a-ut0vec.o \
908+ ../libinnobase_a-ut0wqueue.o
909+5.1: MYSQLOBJS= ../../../mysys/libmysys.a ../../../strings/libmystrings.a
910+5.1: TARGET := xtrabackup_51
911+5.1: $(TARGET)
912+
913+# XtraBackup for MySQL 5.5
914+5.5: INC = -I. -I.. -I./../include -I./../../include -I./../../../include
915+5.5: INNODBOBJS= ../libinnobase.a
916+
917+5.5: MYSQLOBJS= ../../../mysys/libmysys.a ../../../strings/libstrings.a ../../../zlib/libzlib.a
918+ifeq ($(shell uname -s),Linux)
919+5.5: LIBS += -laio
920+endif
921+5.5: TARGET := xtrabackup_innodb55
922+# In CMake server builds it is important to build with exactly the same preprocessor flags
923+# as were used to build InnoDB
924+5.5: DEFS = $(shell grep C_DEFINES ../CMakeFiles/innobase.dir/flags.make | \
925+ sed -e 's/C_DEFINES = //')
926+5.5: $(TARGET)
927+
928+# XtraBackup for XtraDB
929+xtradb: INC=-I. -isystem.. -isystem./../include -isystem./../../include -isystem./../../../include
930+xtradb: INNODBOBJS = ../libinnobase_a-btr0btr.o ../libinnobase_a-btr0cur.o ../libinnobase_a-btr0pcur.o \
931+ ../libinnobase_a-btr0sea.o ../libinnobase_a-buf0buddy.o ../libinnobase_a-buf0buf.o \
932+ ../libinnobase_a-buf0flu.o ../libinnobase_a-buf0lru.o ../libinnobase_a-buf0rea.o \
933+ ../libinnobase_a-data0data.o ../libinnobase_a-data0type.o ../libinnobase_a-dict0boot.o \
934+ ../libinnobase_a-dict0crea.o ../libinnobase_a-dict0dict.o ../libinnobase_a-dict0load.o \
935+ ../libinnobase_a-dict0mem.o ../libinnobase_a-dyn0dyn.o ../libinnobase_a-eval0eval.o \
936+ ../libinnobase_a-eval0proc.o ../libinnobase_a-fil0fil.o ../libinnobase_a-fsp0fsp.o \
937+ ../libinnobase_a-fut0fut.o ../libinnobase_a-fut0lst.o ../libinnobase_a-ha0ha.o \
938+ ../libinnobase_a-ha0storage.o ../libinnobase_a-hash0hash.o ../libinnobase_a-ibuf0ibuf.o \
939+ ../libinnobase_a-lock0iter.o ../libinnobase_a-lock0lock.o ../libinnobase_a-log0log.o \
940+ ../libinnobase_a-log0recv.o ../libinnobase_a-mach0data.o ../libinnobase_a-mem0mem.o \
941+ ../libinnobase_a-mem0pool.o ../libinnobase_a-mtr0log.o ../libinnobase_a-mtr0mtr.o \
942+ ../libinnobase_a-os0file.o ../libinnobase_a-os0proc.o ../libinnobase_a-os0sync.o \
943+ ../libinnobase_a-os0thread.o ../libinnobase_a-page0cur.o ../libinnobase_a-page0page.o \
944+ ../libinnobase_a-page0zip.o ../libinnobase_a-lexyy.o ../libinnobase_a-pars0grm.o \
945+ ../libinnobase_a-pars0opt.o ../libinnobase_a-pars0pars.o ../libinnobase_a-pars0sym.o \
946+ ../libinnobase_a-que0que.o ../libinnobase_a-read0read.o ../libinnobase_a-rem0cmp.o \
947+ ../libinnobase_a-rem0rec.o ../libinnobase_a-row0ext.o ../libinnobase_a-row0ins.o \
948+ ../libinnobase_a-row0merge.o ../libinnobase_a-row0mysql.o ../libinnobase_a-row0purge.o \
949+ ../libinnobase_a-row0row.o ../libinnobase_a-row0sel.o ../libinnobase_a-row0uins.o \
950+ ../libinnobase_a-row0umod.o ../libinnobase_a-row0undo.o ../libinnobase_a-row0upd.o \
951+ ../libinnobase_a-row0vers.o ../libinnobase_a-srv0que.o ../libinnobase_a-srv0srv.o \
952+ ../libinnobase_a-srv0start.o ../libinnobase_a-sync0arr.o ../libinnobase_a-sync0rw.o \
953+ ../libinnobase_a-sync0sync.o ../libinnobase_a-thr0loc.o ../libinnobase_a-trx0purge.o \
954+ ../libinnobase_a-trx0rec.o ../libinnobase_a-trx0roll.o ../libinnobase_a-trx0rseg.o \
955+ ../libinnobase_a-trx0sys.o ../libinnobase_a-trx0trx.o ../libinnobase_a-trx0undo.o \
956+ ../libinnobase_a-usr0sess.o ../libinnobase_a-ut0byte.o ../libinnobase_a-ut0dbg.o \
957+ ../libinnobase_a-ut0list.o ../libinnobase_a-ut0mem.o ../libinnobase_a-ut0rnd.o \
958+ ../libinnobase_a-ut0ut.o ../libinnobase_a-ut0vec.o ../libinnobase_a-ut0wqueue.o \
959+ ../libinnobase_a-ut0rbt.o
960+xtradb: MYSQLOBJS = ../../../mysys/libmysys.a ../../../strings/libmystrings.a ../../../zlib/.libs/libzlt.a
961+xtradb: DEFS += -DXTRADB_BASED
962+xtradb: TARGET := xtrabackup
963+xtradb: $(TARGET)
964+
965+# XtraBackup for XtraDB 5.5
966+xtradb55dbug: DBUG_LIB = ../../../dbug/libdbug.a
967+xtradb55dbug: xtradb55
968+xtradb55: INC=-I. -isystem.. -isystem./../include -isystem./../../include -isystem./../../../include
969+xtradb55: INNODBOBJS = ../libinnobase.a
970+ifeq ($(shell uname -s),Linux)
971+xtradb55: LIBS += -laio
972+endif
973+ifeq "$(wildcard ../../../zlib/.libs/libzlt.a)" ""
974+xtradb55: LIBZ= -lz
975+else
976+xtradb55: LIBZ= ../../../zlib/.libs/libzlt.a
977+endif
978+xtradb55: MYSQLOBJS = ../../../mysys/libmysys.a ../../../strings/libstrings.a $(LIBZ) $(DBUG_LIB)
979+# In CMake server builds it is important to build with exactly the same preprocessor flags
980+# as were used to build InnoDB
981+xtradb55: DEFS = $(shell grep C_DEFINES ../CMakeFiles/innobase.dir/flags.make | \
982+ sed -e 's/C_DEFINES = //')
983+xtradb55: DEFS += -DXTRADB_BASED -DXTRADB55
984+xtradb55: TARGET := xtrabackup_55
985+xtradb55: $(TARGET)
986+
987+
988+xtrabackup.o: xtrabackup.c
989+ $(CC) $(CFLAGS) $(INC) $(DEFS) -c $*.c
990+
991+$(TARGET): xtrabackup.o $(INNODBOBJS) $(MYSQLOBJS)
992+ $(CC) $(CFLAGS) xtrabackup.o $(INNODBOBJS) $(MYSQLOBJS) $(LIBS) -o $(TARGET)
993+
994+clean:
995+ rm -f *.o xtrabackup_*
996+install:
997+ install -m 755 innobackupex-1.5.1 $(BIN_DIR)
998+ install -m 755 xtrabackup_* $(BIN_DIR)
999
1000=== added directory 'plugin/innobase/xtrabackup/doc'
1001=== added file 'plugin/innobase/xtrabackup/doc/xtrabackup.1'
1002--- plugin/innobase/xtrabackup/doc/xtrabackup.1 1970-01-01 00:00:00 +0000
1003+++ plugin/innobase/xtrabackup/doc/xtrabackup.1 2011-03-31 06:44:38 +0000
1004@@ -0,0 +1,1486 @@
1005+.TH "XtraBackup" 1 "January 2011" "" "Percona Inc"
1006+.SH "NAME"
1007+Percona XtraBackup
1008+.SH "DESCRIPTION"
1009+.P
1010+Percona XtraBackup is an open-source hot backup utility for MySQL that doesn't lock your database during the backup. It can back up data from InnoDB, XtraDB, and MyISAM tables on MySQL 5.0 and 5.1 servers, and it has many advanced features. Commercial support is available(http://www.percona.com/support/mysql-support-maintenance/).
1011+.P
1012+Percona XtraBackup is a combination of the xtrabackup C program, and the innobackupex Perl script. The xtrabackup program copies and manipulates InnoDB and XtraDB data files, and the Perl script enables enhanced functionality, such as interacting with a running MySQL server and backing up MyISAM tables. XtraBackup works with unmodified MySQL servers, as well as Percona Server with XtraDB. It runs on Linux, Windows, and FreeBSD.
1013+.P
1014+Summary of features:
1015+
1016+.P
1017+.B
1018+Hot backups.
1019+Backups are online, and queries and transactions continue to run without interruption.
1020+.P
1021+.B
1022+Backs up MyISAM.
1023+MyISAM tables are read-only while they are being backed up.
1024+.P
1025+.B
1026+Partial backups.
1027+You can select which tables and databases to back up.
1028+.P
1029+.B
1030+High performance.
1031+XtraBackup is fast and low-impact. It takes special care not to disrupt your database server. It can copy files in parallel (in multiple threads) for even higher performance.
1032+.P
1033+.B
1034+Remote backups.
1035+You can make local backups, you can stream the backups to other programs, or you can securely copy your backups to a remote host after completion.
1036+.P
1037+.B
1038+Compressed backups.
1039+You can stream a backup into a compressed format. There is a companion program tar4ibd that understands how to work with InnoDB's data format.
1040+.P
1041+.B
1042+Incremental (delta) backups.
1043+You can back up only the data pages that have changed since the last backup.
1044+.P
1045+.B
1046+Point-in-time recovery.
1047+You can recover a backup, and then use binary logs to roll forward to a point in time.
1048+
1049+.SH " Percona XtraBackup User Manual "
1050+
1051+
1052+This page explains how to use Percona XtraBackup. XtraBackup is really a set of three tools:
1053+
1054+.HP
1055+*
1056+.B "xtrabackup"
1057+- a compiled C binary, which copies only InnoDB and XtraDB data
1058+.HP
1059+*
1060+.B "innobackupex"
1061+- a wrapper script that provides functionality to backup a whole MySQL database instance with MyISAM, InnoDB, and XtraDB tables.
1062+.HP
1063+*
1064+.B "tar4ibd"
1065+- tars InnoDB data safely.
1066+
1067+It is possible to use the
1068+.B "xtrabackup"
1069+binary alone, or to use only the
1070+.B "innobackupex"
1071+wrapper script and let it execute
1072+.B "xtrabackup"
1073+for you. It might be helpful to first learn how to use
1074+.B "xtrabackup"
1075+, and then learn how to use
1076+.B "innobackupex"
1077+for convenience and added functionality.
1078+
1079+.SS " How XtraBackup Works "
1080+
1081+
1082+XtraBackup is based on InnoDB's crash-recovery functionality. It copies your InnoDB data files, which results in data that is internally inconsistent; but then it performs crash recovery on the files to make them a consistent, usable database again.
1083+
1084+This works because InnoDB maintains a
1085+.I "redo log"
1086+, also called the transaction log. This contains a record of every change to InnoDB's data. When InnoDB starts, it inspects the data files and the transaction log, and performs two steps. It applies committed transaction log entries to the data files, and it performs an undo operation on any transactions that modified data but did not commit.
1087+
1088+XtraBackup works by remembering the
1089+.I "log sequence number"
1090+(LSN) when it starts, and then copying away the data files. It takes some time to do this, so if the files are changing, then they reflect the state of the database at different points in time. At the same time, XtraBackup runs a background process that watches the transaction log files, and copies changes from it. XtraBackup needs to do this continually because the transaction logs are written in a round-robin fashion, and can be reused after a while. XtraBackup needs the transaction log records for every change to the data files since it began execution.
1091+
1092+The above is the
1093+.I "backup"
1094+process. Next is the
1095+.I "prepare"
1096+process. During this step, XtraBackup performs crash recovery against the copied data files, using the copied transaction log file. After this is done, the database is ready to restore and use.
1097+
1098+The above process is implemented in the
1099+.B "xtrabackup"
1100+compiled binary program. The
1101+.B "innobackupex"
1102+program adds more convenience and functionality by also permitting you to back up MyISAM tables and .frm files. It starts
1103+.B "xtrabackup"
1104+, waits until it finishes copying files, and then issues
1105+.B "FLUSH TABLES WITH READ LOCK"
1106+to prevent further changes to MySQL's data and flush all MyISAM tables to disk. It holds this lock, copies the MyISAM files, and then releases the lock.
1107+
1108+The backed-up MyISAM and InnoDB tables will eventually be consistent with each other, because after the prepare (recovery) process, InnoDB's data is rolled forward to the point at which the backup completed, not rolled back to the point at which it started. This point in time matches where the
1109+.B "FLUSH TABLES WITH READ LOCK"
1110+was taken, so the MyISAM data and the prepared InnoDB data are in sync.
1111+
1112+The
1113+.B "xtrabackup"
1114+and
1115+.B "innobackupex"
1116+tools both offer many features not mentioned in the preceding explanation. Each tool's functionality is explained in more detail on its manual page. In brief, though, the tools permit you to do operations such as streaming and incremental backups with various combinations of copying the data files, copying the log files, and applying the logs to the data.
1117+
1118+.SH " The xtrabackup Binary "
1119+
1120+
1121+The
1122+.B "xtrabackup"
1123+binary is a compiled C program that is linked with the InnoDB libraries and the standard MySQL client libraries. The InnoDB libraries provide functionality necessary to apply a log to data files, and the MySQL client libraries provide command-line option parsing, configuration file parsing, and so on to give the binary a familiar look and feel.
1124+
1125+The next step is to
1126+.B "--prepare"
1127+your backup so it is ready to restore.
1128+The
1129+.B "xtrabackup"
1130+tool runs in either
1131+.B "--backup"
1132+or
1133+.B "--prepare"
1134+mode, corresponding to the two main functions it performs. There are several variations on these functions to accomplish different tasks, and there are two less commonly used modes,
1135+.B "--stats"
1136+and
1137+.B "--print-param"
1138+. There is no need to use any wrapper script with
1139+.B "xtrabackup"
1140+if you don't want to. It is quite easy to use by itself for most purposes.
1141+
1142+This manual section explains how to use xtrabackup in detail.
1143+.SH " Creating a Backup "
1144+
1145+
1146+To create a backup, run
1147+.B "xtrabackup"
1148+with the
1149+.B "--backup"
1150+option. You also need to specify a
1151+.B "--target_dir"
1152+option, which is where the backup will be stored, and a
1153+.B "--datadir"
1154+option, which is where the MySQL data is stored. If the InnoDB data or log files aren't stored in the same directory, you might need to specify the location of those, too. If the target directory does not exist,
1155+.B "xtrabackup"
1156+creates it. If the directory does exist and is empty,
1157+.B "xtrabackup"
1158+will succeed.
1159+.B "xtrabackup"
1160+will not overwrite existing files, however; it will fail with operating system error 17, 'file exists.'
1161+
1162+The tool changes its working directory to the data directory and performs two primary tasks to complete the backup:
1163+
1164+ - It starts a log-copying thread in the background. This thread watches the InnoDB log files, and when they change, it copies the changed blocks to a file called
1165+.B "xtrabackup_logfile"
1166+in the backup target directory. This is necessary because the backup might take a long time, and the recovery process needs all of the log file entries from the beginning to the end of the backup.
1167+ - It copies the InnoDB data files to the target directory. This is not a simple file copy; it opens and reads the files similarly to the way InnoDB does, by reading the data dictionary and copying them a page at a time.
1168+
1169+When the data files are finished copying, xtrabackup stops the log-copying thread, and creates a files in the target directory called
1170+.B "xtrabackup_checkpoints"
1171+, which contains the type of backup performed, the log sequence number at the beginning, and the log sequence number at the end.
1172+
1173+An example command to perform a backup follows:
1174+
1175+
1176+.nf
1177+
1178+xtrabackup --backup --datadir=/var/lib/mysql/ --target-dir=/data/backups/mysql/
1179+
1180+.fi
1181+
1182+This takes a backup of
1183+.B "/var/lib/mysql"
1184+and stores it at
1185+.B "/data/backups/mysql/"
1186+. The
1187+.B "--target-dir"
1188+option deserves special explanation. Because the backup is performed from the data directory itself,
1189+.B "the target directory is relative to the data directory"
1190+unless you specify an absolute path. If you specify a relative path such as
1191+.B "--target-dir=backups"
1192+, for example, don't look for the backup in the directory from which you executed xtrabackup -- it will be a subdirectory of the
1193+.B "--datadir"
1194+directory instead!
1195+
1196+During the backup process, you should see a lot of output showing the data files being copied, as well as the log file thread repeatedly scanning the log files and copying from it. The last thing you should see is something like the following, where the value of the <LSN> will be a number that depends on your system:
1197+
1198+
1199+.nf
1200+
1201+xtrabackup: Transaction log of lsn (<SLN>) to (<LSN>) was copied.
1202+
1203+.fi
1204+
1205+After the backup is finished, the target directory will contain files such as the following, assuming you have a single InnoDB table
1206+.B "test.tbl1"
1207+and you are using
1208+.B "innodb_file_per_table"
1209+:
1210+
1211+
1212+.nf
1213+
1214+/data/backups/mysql/ibdata1
1215+/data/backups/mysql/test
1216+/data/backups/mysql/test/tbl1.ibd
1217+/data/backups/mysql/xtrabackup_checkpoints
1218+/data/backups/mysql/xtrabackup_logfile
1219+
1220+.fi
1221+
1222+The backup can take a long time, depending on how large the database is. It is safe to cancel at any time, because it does not modify the database.
1223+
1224+.SH " Preparing the Backup "
1225+
1226+
1227+After you make a backup with
1228+.B "--backup"
1229+, the next step is to
1230+.I "prepare"
1231+it. The data files are not point-in-time consistent until they've been prepared, because they were copied at different times as the program ran, and they might have been changed while this was happening. If you try to start InnoDB with these data files, it will detect corruption and crash itself to prevent you from running on damaged data. The prepare step makes the files perfectly consistent at a single instant in time, so you can run InnoDB on them.
1232+
1233+During the prepare operation, xtrabackup boots up a kind of modified InnoDB that's embedded inside it (the libraries it was linked against). The modifications are necessary to disable InnoDB's standard safety checks, such as complaining that the log file isn't the right size, which aren't appropriate for working with backups. These modifications are only for the xtrabackup binary; you don't need a modified InnoDB to use xtrabackup for your backups.
1234+
1235+The prepare step uses this "embedded InnoDB" to perform crash recovery on the copied datafiles, using the copied log file. The prepare step is very simple to use: you simply run xtrabackup with the
1236+.B "--prepare"
1237+option and tell it which directory to prepare, for example, to prepare the backup previously taken,
1238+
1239+
1240+.nf
1241+
1242+xtrabackup --prepare --target-dir=/data/backups/mysql/
1243+
1244+.fi
1245+
1246+When this finishes, you should see an "InnoDB shutdown" with a message such as the following, where again the value of <LSN> will depend on your system:
1247+
1248+
1249+.nf
1250+
1251+101107 16:40:15 InnoDB: Shutdown completed; log sequence number <LSN>
1252+
1253+.fi
1254+
1255+Your backup is now clean and consistent, and ready to
1256+.B "restore"
1257+. However, you might want to take an extra step to make restores as quick as possible. This is to prepare the backup a second time. The first time makes the data files perfectly self-consistent, but it doesn't create fresh InnoDB log files. If you restore the backup at this point and start MySQL, it will have to create new log files, which could take a little while, and you might not want to wait for that. If you run
1258+.B "--prepare"
1259+a second time, xtrabackup will create the log files for you, and output status text such as the following, which is abbreviated for clarity. The value of <SIZE> will depend on your MySQL configuration.
1260+
1261+
1262+.nf
1263+
1264+$ xtrabackup --prepare --target-dir=/data/backups/mysql/
1265+xtrabackup: This target seems to be already prepared.
1266+xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.
1267+101107 16:54:10 InnoDB: Log file ./ib_logfile0 did not exist: new to be created
1268+InnoDB: Setting log file ./ib_logfile0 size to <SIZE> MB
1269+InnoDB: Database physically writes the file full: wait...
1270+101107 16:54:10 InnoDB: Log file ./ib_logfile1 did not exist: new to be created
1271+InnoDB: Setting log file ./ib_logfile1 size to <SIZE> MB
1272+InnoDB: Database physically writes the file full: wait...
1273+101107 16:54:15 InnoDB: Shutdown completed; log sequence number 1284108
1274+
1275+.fi
1276+.SH " Restoring a Backup "
1277+
1278+
1279+The xtrabackup binary does not have any functionality for restoring a backup. That is up to the user to do. You might use
1280+.B "rsync"
1281+or
1282+.B "cp"
1283+to restore the files. You should check that the restored files have the correct ownership and permissions.
1284+
1285+Note that xtrabackup backs up only the InnoDB data. You must separately restore the MySQL system database, MyISAM data, table definition files (.frm files), and everything else necessary to make your database functional.
1286+
1287+.SH " How-To and Recipes "
1288+
1289+
1290+This page is a quick-reference list of recipes for the
1291+.B "xtrabackup"
1292+tool. It doesn't mention the
1293+.B "innobackupex"
1294+tool; that is documented separately.
1295+
1296+In all of the below examples, we assume the following:
1297+
1298+.HP
1299+* You are backing up a server whose data is stored in
1300+.B "/var/lib/mysql/"
1301+, which is the standard location for most distributions
1302+.HP
1303+* You are storing the backups in
1304+.B "/data/backups/mysql"
1305+
1306+.HP
1307+* You have a
1308+.B "my.cnf"
1309+file in a standard location, such as
1310+.B "/etc/my.cnf"
1311+, with at least the following contents:
1312+.nf
1313+[mysqld]
1314+datadir=/var/lib/mysql/
1315+[xtrabackup]
1316+target_dir=/data/backups/mysql/
1317+
1318+.fi
1319+
1320+.SS " Making a Backup "
1321+
1322+
1323+Making the backup copies the InnoDB data and log files to the destination. Preparing the backup makes the data files consistent and ready to use.
1324+
1325+.HP
1326+* Make a backup:
1327+.nf
1328+xtrabackup --backup
1329+.fi
1330+.HP
1331+* Prepare the backup:
1332+.nf
1333+xtrabackup --prepare
1334+.fi
1335+.HP
1336+* Prepare again, to create fresh InnoDB log files:
1337+.nf
1338+xtrabackup --prepare
1339+.fi
1340+
1341+
1342+.B "Success Criterion"
1343+
1344+
1345+.HP
1346+* The exit status of
1347+.B "xtrabackup"
1348+is 0.
1349+.HP
1350+* In the second
1351+.B "--prepare"
1352+step, you should see InnoDB print messages similar to "Log file ./ib_logfile0 did not exist: new to be created", followed by a line indicating the log file was created.
1353+
1354+
1355+.B "Relevant Configuration"
1356+
1357+
1358+.HP
1359+* You might want to set the
1360+.B "--use-memory"
1361+option to something similar to the size of your buffer pool, if you are on a dedicated server that has enough free memory.
1362+
1363+.SS " Making an Incremental Backup "
1364+
1365+
1366+Making an incremental backup requires a full backup as a base.
1367+
1368+.HP
1369+* Create a full backup as above, but do not run the
1370+.B "--prepare"
1371+command yet
1372+.HP
1373+* Suppose the full backup is on Monday
1374+.HP
1375+* Create an incremental backup on Tuesday:
1376+.nf
1377+
1378+ xtrabackup --backup --target-dir=/data/backups/inc/tue/ \
1379+ --incremental-basedir=/data/backups/mysql/
1380+.fi
1381+.HP
1382+* Create an incremental backup on Wednesday:
1383+.nf
1384+
1385+ xtrabackup --backup --target-dir=/data/backups/inc/wed/ \
1386+ --incremental-basedir=/data/backups/inc/tue/
1387+.fi
1388+.HP
1389+* Prepare the base backup from Monday:
1390+.nf
1391+
1392+ xtrabackup --prepare --apply-log-only --target-dir=/data/backups/mysql/
1393+.fi
1394+.HP
1395+* Roll Monday's data forward to the state on Tuesday:
1396+.nf
1397+
1398+ xtrabackup --prepare --apply-log-only --target-dir=/data/backups/mysql/ \
1399+ --incremental-dir=/data/backups/inc/tue/
1400+.fi
1401+.HP
1402+* Roll forward again to the state on Wednesday:
1403+.nf
1404+
1405+ xtrabackup --prepare --apply-log-only --target-dir=/data/backups/mysql/ \
1406+ --incremental-dir=/data/backups/inc/wed/
1407+.fi
1408+.HP
1409+* Follow the steps for a normal backup to complete the preparation stage so the backup is ready to restore
1410+
1411+.SS " Restoring the Backup "
1412+
1413+
1414+Because
1415+.B "xtrabackup"
1416+doesn't copy MyISAM files, .frm files, and the rest of the database, you might need to back those up separately. To restore the InnoDB data, simply do something like the following after preparing:
1417+
1418+
1419+.nf
1420+
1421+cd /data/backups/mysql/
1422+rsync -rvt --exclude 'xtrabackup_checkpoints' --exclude 'xtrabackup_logfile' \
1423+ ./ /var/lib/mysql
1424+chown -R mysql:mysql /var/lib/mysql/
1425+
1426+.fi
1427+.SH " Limitations of xtrabackup "
1428+
1429+
1430+The xtrabackup binary has some limitations you should be aware of to ensure that your backups go smoothly and are recoverable.
1431+
1432+.HP
1433+* If the xtrabackup_logfile is larger than 4GB, the
1434+.B "--prepare"
1435+step will fail on 32-bit versions of xtrabackup. This limitation also applied to some older 64-bit versions of xtrabackup (
1436+.B FIXME
1437+what versions?).
1438+.HP
1439+* xtrabackup does not currently create new InnoDB log files (ib_logfile0, etc) during the initial
1440+.B "--prepare"
1441+step. You must prepare the backup a second time to do this, if you wish.
1442+.HP
1443+* xtrabackup copies only the InnoDB data and logs. It does not copy table definition files (.frm files), MyISAM data, users, privileges, or any other portions of the overall database that lie outside of the InnoDB data. To back up this data, you need a wrapper script such as
1444+.B "innobackupex"
1445+.
1446+.HP
1447+*
1448+.B "xtrabackup"
1449+doesn't understand the very old
1450+.B "--set-variable"
1451+
1452+.B "my.cnf"
1453+syntax that MySQL uses. See
1454+.B "configuration"
1455+.
1456+.SH " Configuring xtrabackup "
1457+
1458+
1459+This page explains how to configure
1460+.B "xtrabackup"
1461+and how to configure your system to support
1462+.B "xtrabackup"
1463+correctly.
1464+
1465+.SS " Configuring xtrabackup "
1466+
1467+
1468+All of the
1469+.B "xtrabackup"
1470+configuration is through options, which behave exactly like standard MySQL program options: they can be specified either at the command-line, or through a file such as /etc/my.cnf.
1471+
1472+The xtrabackup binary reads the [myslqd] and [xtrabackup] sections from any configuration files, in order. That is so that it can read its options from your existing MySQL installation, such as the
1473+.B "datadir"
1474+or some of the InnoDB options. If you want to override these, just specify them in the [xtrabackup] section, and because it is read later, it will take precedence.
1475+
1476+You don't need to put any configuration in your my.cnf if you don't want to. You can simply specify the options on the command-line. Normally, the only thing you might find convenient to place in the [xtrabackup] section of your my.cnf file is the
1477+.B "target_dir"
1478+option, for example,
1479+
1480+
1481+.nf
1482+
1483+[xtrabackup]
1484+target_dir = /data/backups/mysql/
1485+
1486+.fi
1487+
1488+This manual will assume that you
1489+.B "do not"
1490+have any file-based configuration for
1491+.B "xtrabackup"
1492+, so it will always show command-line options being used explicitly. Please see the
1493+.B "option and variable reference"
1494+for details on all of the configuration options.
1495+
1496+The
1497+.B "xtrabackup"
1498+binary does not accept exactly the same syntax in the
1499+.B "my.cnf"
1500+file as the
1501+.B "mysqld"
1502+server binary does. For historical reasons, the
1503+.B "mysqld"
1504+server binary accepts parameters with a
1505+.B "--set-variable=<variable>=<value>"
1506+syntax, which
1507+.B "xtrabackup"
1508+does not understand. If your
1509+.B "my.cnf"
1510+file has such configuration directives, you should rewrite them in the
1511+.B "--variable=value"
1512+syntax.
1513+
1514+.SS " System Configuration and NFS Volumes "
1515+
1516+
1517+The
1518+.B "xtrabackup"
1519+tool requires no special configuration on most systems. However, the storage where the
1520+.B "--target-dir"
1521+is located must behave properly when
1522+.B "fsync()"
1523+is called. In particular, we have noticed that NFS volumes not mounted with the
1524+.B "sync"
1525+option might not really sync the data. As a result, if you back up to an NFS volume mounted with the
1526+.B "async"
1527+option, and then try to prepare the backup from a different server that also mounts that volume, the data might appear to be corrupt. You can use the
1528+.B "noasync"
1529+mount option to avoid this problem.
1530+.SH " The xtrabackup Option Reference "
1531+
1532+
1533+This page documents all of the command-line options for the
1534+.B "xtrabackup"
1535+binary.
1536+
1537+.SS " --print-defaults "
1538+
1539+
1540+Print the program argument list and exit. Must be given as the first option on the command-line.
1541+
1542+.SS " --no-defaults "
1543+
1544+
1545+Don't read default options from any option file. Must be given as the first option on the command-line.
1546+
1547+.SS " --defaults-file "
1548+
1549+
1550+Only read default options from the given file. Must be given as the first option on the command-line. Must be a real file; cannot be a symbolic link.
1551+
1552+.SS " --defaults-extra-file "
1553+
1554+
1555+Read this file after the global files are read. Must be given as the first option on the command-line.
1556+
1557+.SS " --apply-log-only "
1558+
1559+
1560+This option causes only the redo stage to be performed when
1561+.B "incremental backups"
1562+.
1563+
1564+.SS " --backup "
1565+
1566+
1567+Make a backup and place it in
1568+.B "--target-dir"
1569+. See
1570+.B "creating a backup"
1571+.
1572+
1573+.SS " --create-ib-logfile "
1574+
1575+
1576+This option is not currently implemented. To create the InnoDB log files, you must
1577+.B "prepare the backup"
1578+twice at present.
1579+
1580+.SS " --datadir "
1581+
1582+
1583+The source directory for the backup. This should be the same as the datadir for your MySQL server, so it should be read from
1584+.B "my.cnf"
1585+if that exists; otherwise you must specify it on the command line.
1586+
1587+.SS " --export "
1588+
1589+
1590+Create files necessary for exporting tables. See [[export and import]].
1591+
1592+.SS " --incremental-basedir "
1593+
1594+
1595+When creating an
1596+.B "incremental backup"
1597+, this is the directory containing the full backup that is the base dataset for the incremental backups.
1598+
1599+.SS " --incremental-dir "
1600+
1601+
1602+When preparing an
1603+.B "incremental backup"
1604+, this is the directory where the incremental backup is combined with the full backup to make a new full backup.
1605+
1606+.SS " --incremental-lsn "
1607+
1608+
1609+When creating an
1610+.B "incremental backup"
1611+, you can specify the log sequence number (LSN) in high:low format as two 32-bit integers instead of specifying
1612+.B "--incremental-basedir"
1613+.
1614+
1615+.SS " --innodb-miscellaneous "
1616+
1617+
1618+There is a large group of InnoDB options that are normally read from the
1619+.B "my.cnf"
1620+configuration file, so that
1621+.B "xtrabackup"
1622+boots up its embedded InnoDB in the same configuration as your current server. You normally do not need to specify these explicitly. These options have the same behavior that they have in InnoDB or XtraDB. They are as follows:
1623+
1624+.HP
1625+*
1626+.B "--innodb-adaptive-hash-index"
1627+
1628+.HP
1629+*
1630+.B "--innodb-additional-mem-pool-size"
1631+
1632+.HP
1633+*
1634+.B "--innodb-autoextend-increment"
1635+
1636+.HP
1637+*
1638+.B "--innodb-buffer-pool-size"
1639+
1640+.HP
1641+*
1642+.B "--innodb-checksums"
1643+
1644+.HP
1645+*
1646+.B "--innodb-data-file-path"
1647+
1648+.HP
1649+*
1650+.B "--innodb-data-home-dir"
1651+
1652+.HP
1653+*
1654+.B "--innodb-doublewrite-file"
1655+
1656+.HP
1657+*
1658+.B "--innodb-doublewrite"
1659+
1660+.HP
1661+*
1662+.B "--innodb-extra-undoslots"
1663+
1664+.HP
1665+*
1666+.B "--innodb-fast-checksum"
1667+
1668+.HP
1669+*
1670+.B "--innodb-file-io-threads"
1671+
1672+.HP
1673+*
1674+.B "--innodb-file-per-table"
1675+
1676+.HP
1677+*
1678+.B "--innodb-flush-log-at-trx-commit"
1679+
1680+.HP
1681+*
1682+.B "--innodb-flush-method"
1683+
1684+.HP
1685+*
1686+.B "--innodb-force-recovery"
1687+
1688+.HP
1689+*
1690+.B "--innodb-io-capacity"
1691+
1692+.HP
1693+*
1694+.B "--innodb-lock-wait-timeout"
1695+
1696+.HP
1697+*
1698+.B "--innodb-log-buffer-size"
1699+
1700+.HP
1701+*
1702+.B "--innodb-log-files-in-group"
1703+
1704+.HP
1705+*
1706+.B "--innodb-log-file-size"
1707+
1708+.HP
1709+*
1710+.B "--innodb-log-group-home-dir"
1711+
1712+.HP
1713+*
1714+.B "--innodb-max-dirty-pages-pct"
1715+
1716+.HP
1717+*
1718+.B "--innodb-open-files"
1719+
1720+.HP
1721+*
1722+.B "--innodb-page-size"
1723+
1724+.HP
1725+*
1726+.B "--innodb-read-io-threads"
1727+
1728+.HP
1729+*
1730+.B "--innodb-write-io-threads"
1731+
1732+
1733+.SS " --log-stream "
1734+
1735+
1736+Makes
1737+.B "xtrabackup"
1738+not copy data files, and output the contents of the InnoDB log files to STDOUT until the
1739+.B "--suspend-at-end"
1740+automatically.
1741+
1742+.SS " --prepare "
1743+
1744+
1745+Makes
1746+.B "xtrabackup"
1747+perform recovery on a backup created with
1748+.B "--backup"
1749+, so that it is ready to use. See
1750+.B "preparing a backup"
1751+.
1752+
1753+.SS " --print-param "
1754+
1755+
1756+Makes
1757+.B "xtrabackup"
1758+print out parameters that can be used for copying the data files back to their original locations to restore them. See
1759+.B "scripting with xtrabackup"
1760+.
1761+
1762+.SS " --stats "
1763+
1764+
1765+Causes
1766+.B "xtrabackup"
1767+to scan the specified data files and print out
1768+.B "index statistics"
1769+.
1770+
1771+.SS " --suspend-at-end "
1772+
1773+
1774+Causes
1775+.B "xtrabackup"
1776+to create a file called
1777+.B "xtrabackup_suspended"
1778+in the
1779+.B "scripting with xtrabackup"
1780+.
1781+
1782+.SS " --tables-file "
1783+
1784+
1785+A file containing one table name per line, in
1786+.B "databasename.tablename"
1787+format. The backup will be limited to the specified tables. See
1788+.B "partial backups"
1789+.
1790+
1791+.SS " --tables "
1792+
1793+
1794+A regular expression against which the full tablename, in
1795+.B "databasename.tablename"
1796+format, is matched. If the name matches, the table is backed up. See
1797+.B "partial backups"
1798+.
1799+
1800+.SS " --target-dir "
1801+
1802+
1803+This option specifies the destination directory for the backup. If the directory does not exist,
1804+.B "xtrabackup"
1805+creates it. If the directory does exist and is empty,
1806+.B "xtrabackup"
1807+will succeed.
1808+.B "xtrabackup"
1809+will not overwrite existing files, however; it will fail with operating system error 17, 'file exists.'
1810+
1811+Note that for
1812+.B "--prepare"
1813+, relative paths are interpreted as being relative to the current working directory.
1814+
1815+.SS " --throttle "
1816+
1817+
1818+This option limits
1819+.B "throttling a backup"
1820+.
1821+
1822+.SS " --tmpdir "
1823+
1824+
1825+This option is currently not used for anything except printing out the correct
1826+.B "tmpdir"
1827+parameter when
1828+.B "--print-param"
1829+is used.
1830+
1831+.SS " --use-memory "
1832+
1833+
1834+This option affects how much memory is allocated for
1835+.B "--stats"
1836+. Its purpose is similar to
1837+.B "innodb_buffer_pool_size"
1838+. It does not do the same thing as the similarly named option in Oracle's InnoDB Hot Backup tool. The default value is 100MB, and if you have enough available memory, 1GB to 2GB is a good recommended value.
1839+
1840+.SS " --parallel "
1841+
1842+
1843+This option specifies the number of threads to use to copy multiple data files concurrently when creating a backup. The default value is 1 (i.e., no concurrent transfer).
1844+
1845+Currently, the option only works for local backups.
1846+
1847+.SH " Exporting and Importing Tables "
1848+
1849+
1850+In standard InnoDB, it is not normally possible to copy tables between servers by copying the files, even with
1851+.B "innodb_file_per_table"
1852+. However, with the xtrabackup binary, you can export individual tables from any InnoDB database, and import them into Percona Server with XtraDB. (The source doesn't have to be XtraDB, but the destination does.) This functionality requires
1853+.B "innodb_file_per_table"
1854+to be used on both servers, and requires
1855+.B "innodb_expand_import"
1856+to be enabled on the destination server. It only works on individual
1857+.B ".ibd"
1858+files, and cannot export a table that is not contained in its own
1859+.B ".ibd"
1860+file.
1861+
1862+Let's see how to export and import the following table:
1863+
1864+
1865+.nf
1866+
1867+CREATE TABLE export_test (
1868+ a int(11) DEFAULT NULL
1869+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
1870+
1871+.fi
1872+
1873+.SS " Exporting the Table "
1874+
1875+
1876+This table should have been created in innodb_file_per_table mode, so after taking a backup as usual with
1877+.B "--backup"
1878+, the
1879+.B ".ibd"
1880+file should exist in the target directory:
1881+
1882+
1883+.nf
1884+
1885+$ find /data/backups/mysql/ -name export_test.*
1886+/data/backups/mysql/test/export_test.ibd
1887+
1888+.fi
1889+
1890+when you prepare the backup, add the extra parameter
1891+.B "--export"
1892+to the command. If you do not have
1893+.B "innodb_file_per_table"
1894+in your my.cnf, you must add that to the command-line options. Here is an example:
1895+
1896+
1897+.nf
1898+
1899+xtrabackup --prepare --export --innodb-file-per-table --target-dir=/data/backups/mysql/
1900+
1901+.fi
1902+
1903+Now you should see a
1904+.B ".exp"
1905+file in the target directory:
1906+
1907+
1908+.nf
1909+
1910+$ find /data/backups/mysql/ -name export_test.*
1911+/data/backups/mysql/test/export_test.exp
1912+/data/backups/mysql/test/export_test.ibd
1913+
1914+.fi
1915+
1916+These two files are all you need to import the table into a server running Percona Server with XtraDB.
1917+
1918+.SS " Importing the Table "
1919+
1920+
1921+On the destination server running Percona Server with XtraDB, with
1922+.B "innodb_expand_import"
1923+enabled, create a table with the same structure, and then perform the following steps:
1924+
1925+ - Execute
1926+.B "ALTER TABLE test.export_test DISCARD TABLESPACE;"
1927+
1928+ - If you see the following message, then you must enable innodb_file_per_table and create the table again: "ERROR 1030 (HY000): Got error -1 from storage engine"
1929+ - Copy the exported files to the
1930+.B "test/"
1931+subdirectory of the destination server's data directory
1932+ - Execute
1933+.B "ALTER TABLE test.export_test IMPORT TABLESPACE;"
1934+
1935+
1936+The table should now be imported, and you should be able to SELECT from it and see the imported data.
1937+
1938+.SH " Incremental Backups "
1939+
1940+
1941+The
1942+.B "xtrabackup"
1943+tool supports incremental backups, which means that it can copy only the data that has changed since the last full backup. You can perform many incremental backups between each full backup, so you can set up a backup process such as a full backup once a week and an incremental backup every day, or full backups every day and incremental backups every hour.
1944+
1945+Incremental backups work because each InnoDB page (usually 16kb in size) contains a
1946+.I "log sequence number"
1947+, or LSN. The LSN is the system version number for the entire database. Each page's LSN shows how recently it was changed. An incremental backup copies each page whose LSN is newer than the previous incremental or full backup's LSN.
1948+
1949+Incremental backups do not actually compare the data files to the previous backup's data files. In fact, you can use
1950+.B "--incremental-lsn"
1951+to perform an incremental backup without even having the previous backup, if you know its LSN. Incremental backups simply read the pages and compare their LSN to the last backup's LSN. You still need a full backup to recover the incremental changes, however; without a full backup to act as a base, the incremental backups are useless.
1952+
1953+.SS " Creating an Incremental Backup "
1954+
1955+
1956+To make an incremental backup, begin with a full backup as usual. The xtrabackup binary writes a file called xtrabackup_checkpoints into the backup's target directory. This file contains a line showing the
1957+.B "to_lsn"
1958+, which is the database's LSN at the end of the backup. Create the full backup with a command such as the following:
1959+
1960+
1961+.nf
1962+
1963+xtrabackup --backup --target-dir=/data/backups/base --datadir=/var/lib/mysql/
1964+
1965+.fi
1966+
1967+
1968+.B "TIP:"
1969+If you want a
1970+.B "usable"
1971+full backup, use innobackupex since xtrabackup itself won't copy table definitions, triggers, or anything else that's not .ibd.
1972+
1973+
1974+If you look at the xtrabackup_checkpoints file, you should see some contents similar to the following:
1975+
1976+
1977+.nf
1978+
1979+backup_type = full-backuped
1980+from_lsn = 0
1981+to_lsn = 1291135
1982+
1983+.fi
1984+
1985+Now that you have a full backup, you can make an incremental backup based on it. Use a command such as the following:
1986+
1987+
1988+.nf
1989+
1990+xtrabackup --backup --target-dir=/data/backups/inc1 \
1991+ --incremental-basedir=/data/backups/base --datadir=/var/lib/mysql/
1992+
1993+.fi
1994+
1995+The
1996+.B "/data/backups/inc1/"
1997+directory should now contain delta files, such as
1998+.B "ibdata1.delta"
1999+and
2000+.B "test/table1.ibd.delta"
2001+. These represent the changes since the LSN 1291135. If you examine the
2002+.B "xtrabackup_checkpoints"
2003+file in this directory, you should see something similar to the following:
2004+
2005+
2006+.nf
2007+
2008+backup_type = incremental
2009+from_lsn = 1291135
2010+to_lsn = 1291340
2011+
2012+.fi
2013+
2014+The meaning should be self-evident. It's now possible to use this directory as the base for yet another incremental backup:
2015+
2016+
2017+.nf
2018+
2019+xtrabackup --backup --target-dir=/data/backups/inc2 \
2020+ --incremental-basedir=/data/backups/inc1 --datadir=/var/lib/mysql/
2021+
2022+.fi
2023+
2024+.SS " Preparing the Backups "
2025+
2026+
2027+The
2028+.B "--prepare"
2029+step for incremental backups is not the same as for normal backups. In normal backups, two types of operations are performed to make the database consistent: committed transactions are replayed from the log file against the data files, and uncommitted transactions are rolled back. For technical reasons, you must skip the rollback of uncommitted transactions when preparing a backup that will be used as the base for an incremental backup. You should use the
2030+.B "--apply-log-only"
2031+option to prevent the rollback phase.
2032+
2033+
2034+.B "WARNING:"
2035+If you do not use the
2036+.B "--apply-log-only"
2037+option to prevent the rollback phase, then your incremental backups will be useless. After transactions have been rolled back, further incremental backups cannot be applied.
2038+
2039+
2040+Beginning with the full backup you created, you can prepare it, and then apply the incremental differences to it. Recall that you have the following backups:
2041+
2042+
2043+.nf
2044+
2045+/data/backups/base
2046+/data/backups/inc1
2047+/data/backups/inc2
2048+
2049+.fi
2050+
2051+To prepare the base backup, you need to run
2052+.B "--prepare"
2053+as usual, but prevent the rollback phase:
2054+
2055+
2056+.nf
2057+
2058+xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base
2059+
2060+.fi
2061+
2062+The output should end with some text such as the following:
2063+
2064+ 101107 20:49:43 InnoDB: Shutdown completed; log sequence number 1291135
2065+
2066+The log sequence number should match the to_lsn of the base backup, which you saw previously.
2067+
2068+This backup is actually safe to restore as-is now, even though the rollback phase has been skipped. If you restore it and start MySQL, InnoDB will detect that the rollback phase was not performed, and it will do that in the background, as it usually does for a crash recovery upon start. It will notify you that the database was not shut down normally, but the recovery phase should be nearly instantaneous, because the redo log has already been applied to the data files.
2069+
2070+To apply the first incremental backup to the full backup, you should use the following command:
2071+
2072+
2073+.nf
2074+
2075+xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base \
2076+ --incremental-dir=/data/backups/inc1
2077+
2078+.fi
2079+
2080+This applies the delta files to the files in /data/backups/base, which rolls them forward in time to the time of the incremental backup. It then applies the redo log as usual to the result. The final data is in /data/backups/base,
2081+.B "not"
2082+in the incremental directory. You should see some output such as the following:
2083+
2084+
2085+.nf
2086+
2087+incremental backup from 1291135 is enabled.
2088+xtrabackup: cd to /data/backups/base/
2089+xtrabackup: This target seems to be already prepared.
2090+xtrabackup: xtrabackup_logfile detected: size=2097152, start_lsn=(1291340)
2091+Applying /data/backups/inc1/ibdata1.delta ...
2092+Applying /data/backups/inc1/test/table1.ibd.delta ...
2093+.... snip
2094+101107 20:56:30 InnoDB: Shutdown completed; log sequence number 1291340
2095+
2096+.fi
2097+
2098+Again, the LSN should match what you saw from your earlier inspection of the first incremental backup. If you restore the files from /data/backups/base, you should see the state of the database as of the first incremental backup.
2099+
2100+Preparing the second incremental backup is a similar process: apply the deltas to the (modified) base backup, and you will roll its data forward in time to the point of the second incremental backup:
2101+
2102+
2103+.nf
2104+
2105+xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base \
2106+ --incremental-dir=/data/backups/inc2
2107+
2108+.fi
2109+
2110+If you wish to avoid the notice that InnoDB was not shut down normally, when you have applied the desired deltas to the base backup, you can run
2111+.B "--prepare"
2112+again without disabling the rollback phase.
2113+.SH " Partial Backups "
2114+
2115+
2116+xtrabackup supports taking partial backups when
2117+.B "innodb_file_per_table"
2118+is enabled. There are two ways to create partial backups.
2119+
2120+For the purposes of this manual page, we will assume that there is a database named 'test' which contains tables named 't1' and 't2'.
2121+
2122+.SS " Using the --tables Option "
2123+
2124+
2125+The first method is with the
2126+.B "--tables"
2127+option. The option's value is a regular expression that is matched against the fully qualified tablename, including the database name, in the form
2128+.B "databasename.tablename"
2129+.
2130+
2131+To back up only tables in the 'test' database, you can use the following command:
2132+
2133+ xtrabackup --backup --datadir=/var/lib/mysql --target-dir=/data/backups/ \
2134+ --tables="^test[.].*"
2135+
2136+To back up only the table 'test.t1', you can use the following command:
2137+
2138+ xtrabackup --backup --datadir=/var/lib/mysql --target-dir=/data/backups/ \
2139+ --tables="^test[.]t1"
2140+
2141+.SS " Using the --tables-file Option "
2142+
2143+
2144+The
2145+.B "--tables-file"
2146+option specifies a file that can contain multiple table names, one table name per line in the file. Only the tables named in the file will be backed up. Names are matched exactly, case-sensitive, with no pattern or regular expression matching. The table names must be fully qualified, in
2147+.B "databasename.tablename"
2148+format.
2149+
2150+.SS " Preparing the Backup "
2151+
2152+
2153+When you use the
2154+.B "--prepare"
2155+option on a partial backup, you will see warnings about tables that don't exist. That is because these tables exist in the data dictionary inside InnoDB, but the corresponding
2156+.B ".ibd"
2157+files don't exist. They were not copied into the backup directory. These tables will be removed from the data dictionary, and when you restore the backup and start InnoDB, they will no longer exist and will not cause any errors or warnings to be printed to the log file.
2158+
2159+An example of the error message you will see during the prepare phase follows.
2160+
2161+
2162+.nf
2163+
2164+InnoDB: Reading tablespace information from the .ibd files...
2165+101107 22:31:30 InnoDB: Error: table 'test1/t'
2166+InnoDB: in InnoDB data dictionary has tablespace id 6,
2167+InnoDB: but tablespace with that id or name does not exist. It will be removed from data dictionary.
2168+
2169+.fi
2170+
2171+.SH " Analyzing Table Statistics "
2172+
2173+
2174+The
2175+.B "xtrabackup"
2176+binary can analyze InnoDB data files in read-only mode to give statistics about them. To do this, you should use the
2177+.B "--stats"
2178+option. You can combine this with the
2179+.B "--tables"
2180+option to limit the files to examine. It also uses the
2181+.B "--use-memory="
2182+option.
2183+
2184+You can perform the analysis on a running server, with some chance of errors due to the data being changed during analysis. Or, you can analyze a backup copy of the database. Either way, to use the statistics feature, you need a clean copy of the database including correctly sized log files, so you need to execute with
2185+.B "--prepare"
2186+twice to use this functionality on a backup.
2187+
2188+The result of running on a backup might look like the following:
2189+
2190+
2191+.nf
2192+
2193+<INDEX STATISTICS>
2194+ table: test/table1, index: PRIMARY, space id: 12, root page 3
2195+ estimated statistics in dictionary:
2196+ key vals: 25265338, leaf pages 497839, size pages 498304
2197+ real statistics:
2198+ level 2 pages: pages=1, data=5395 bytes, data/pages=32%
2199+ level 1 pages: pages=415, data=6471907 bytes, data/pages=95%
2200+ leaf pages: recs=25958413, pages=497839, data=7492026403 bytes, data/pages=91%
2201+
2202+.fi
2203+
2204+This can be interpreted as follows:
2205+
2206+.HP
2207+* The first line simply shows the table and index name and its internal identifiers. If you see an index named
2208+.B "GEN_CLUST_INDEX"
2209+, that is the table's clustered index, automatically created because you did not explicitly create a PRIMARY KEY.
2210+.HP
2211+* The
2212+.I "estimated statistics in dictionary"
2213+information is similar to the data that's gathered through
2214+.B "ANALYZE TABLE"
2215+inside of InnoDB to be stored as estimated cardinality statistics and passed to the query optimizer
2216+.HP
2217+* The
2218+.I "real statistics"
2219+information is the result of scanning the data pages and computing exact information about the index.
2220+.HP
2221+* The
2222+.B "level <X> pages:"
2223+output means that the line shows information about pages at that level in the index tree. The larger <X> is, the farther it is from the leaf pages, which are level 0. The first line is the root page.
2224+.HP
2225+* The
2226+.B "leaf pages"
2227+output shows the leaf pages, of course. This is where the table's data is stored.
2228+.HP
2229+* The
2230+.B "external pages:"
2231+output (not shown) shows large external pages that hold values too long to fit in the row itself, such as long BLOB and TEXT values.
2232+.HP
2233+* The
2234+.I "recs"
2235+is the real number of records (rows) in leaf pages.
2236+.HP
2237+* The
2238+.I "pages"
2239+is the page count.
2240+.HP
2241+* The
2242+.I "data"
2243+is the total size of the data in the pages, in bytes.
2244+.HP
2245+* The
2246+.I "data/pages"
2247+is calculated as (data / (pages * PAGE_SIZE)) * 100%. It will never reach 100% because of space reserved for page headers and footers.
2248+
2249+
2250+.SH " Throttling Backups "
2251+
2252+
2253+Although
2254+.B "xtrabackup"
2255+does not block your database's operation, any backup can add load to the system being backed up. On systems that do not have much spare I/O capacity, it might be helpful to throttle the rate at which
2256+.B "xtrabackup"
2257+reads and writes data. You can do this with the
2258+.B "--throttle"
2259+option.
2260+
2261+In
2262+.B "--backup"
2263+mode, this option limits the number of pairs of read-and-write operations per second that
2264+.B "xtrabackup"
2265+will perform. If you are creating an
2266+.B "incremental backup"
2267+, then the limit is the number of read IO operations per second.
2268+
2269+By default, there is no throttling, and
2270+.B "xtrabackup"
2271+reads and writes data as quickly as it can. If you set too strict of a limit on the I/O operations, the backup might be so slow that it will never catch up with the transaction logs that InnoDB is writing, so the backup might never complete.
2272+
2273+.SH " Working with Binary Logs "
2274+
2275+
2276+The
2277+.B "xtrabackup"
2278+binary integrates with information that InnoDB stores in its transaction log about the corresponding binary log position for committed transactions. This enables it to print out the binary log position to which a backup corresponds, so you can use it to set up new replication slaves or perform point-in-time recovery.
2279+
2280+.SS " Finding the Binary Log Position "
2281+
2282+
2283+You can find the binary log position corresponding to a backup performing the
2284+.B "--prepare"
2285+process. If your backup is from a server with binary logging enabled,
2286+.B "xtrabackup"
2287+will create a file named
2288+.B "xtrabackup_binlog_pos_innodb"
2289+in the target directory. This file contains the binary log file name and position of the exact point in the binary log to which the prepared backup corresponds.
2290+
2291+You will also see output similar to the following during the prepare stage:
2292+
2293+
2294+.nf
2295+
2296+InnoDB: Last MySQL binlog file position 0 3252710, file name ./mysql-bin.000001
2297+... snip ...
2298+[notice (again)]
2299+ If you use binary log and don't use any hack of group commit,
2300+ the binary log position seems to be:
2301+InnoDB: Last MySQL binlog file position 0 3252710, file name ./mysql-bin.000001
2302+
2303+.fi
2304+
2305+The output should contain the same file name and position as the
2306+.B "xtrabackup_binlog_pos_innodb"
2307+file. The message about hacking group commit refers to an early implementation of emulated group commit in Percona Server.
2308+.B FIXME
2309+is this still uncertain, or do we know that it works correctly now?
2310+
2311+.SS " Point-In-Time Recovery "
2312+
2313+
2314+To perform a point-in-time recovery from an
2315+.B "xtrabackup"
2316+backup, you should prepare and restore the backup, and then replay binary logs from the point shown in the
2317+.B "xtrabackup_binlog_pos_innodb"
2318+file.
2319+
2320+.SS " Setting Up a New Replication Slave "
2321+
2322+
2323+To set up a new replica, you should prepare the backup, and restore it to the data directory of your new replication slave. Then in your
2324+.B "CHANGE MASTER TO"
2325+command, use the binary log filename and position shown in the
2326+.B "xtrabackup_binlog_pos_innodb"
2327+file to start replication.
2328+
2329+.SH " Scripting Backups With xtrabackup "
2330+
2331+
2332+The
2333+.B "xtrabackup"
2334+tool has several features to enable scripts to control it while they perform related tasks. The
2335+.B "innobackupex"
2336+script is one example, but xtrabackup is easy to control with your own command-line scripts too.
2337+
2338+.SS " Suspending After Copying "
2339+
2340+
2341+In
2342+.B "backup"
2343+mode, xtrabackup normally copies the log files in a background thread, copies the data files in a foreground thread, and then stops the log copying thread and finishes. If you use the
2344+.B "--suspend-at-end"
2345+option, instead of stopping the log thread and finishing, xtrabackup continues to copy the log files, and creates a file in the target directory called
2346+.B "xtrabackup_suspended"
2347+. As long as that file exists,
2348+.B "xtrabackup"
2349+will continue to watch the log files and copy them into the
2350+.B "xtrabackup_logfile"
2351+in the target directory. When the file is removed,
2352+.B "xtrabackup"
2353+will finish copying the log file and exit.
2354+
2355+This functionality is useful for coordinating the InnoDB data backups with other actions. Perhaps the most obvious is copying the table definitions (the .frm files) so that the backup can be restored. You can start
2356+.B "xtrabackup"
2357+in the background, wait for the
2358+.B "xtrabackup_suspended"
2359+file to be created, and then copy any other files you need to complete the backup. This is exactly what the
2360+.B "innobackupex"
2361+tool does (it also copies MyISAM data and other files).
2362+
2363+.SS " Generating Meta-Data "
2364+
2365+
2366+It is a good idea for the backup to include all the information you need to restore the backup. The
2367+.B "xtrabackup"
2368+tool can print out the contents of a
2369+.B "my.cnf"
2370+file that are needed to restore the data and log files. If you add the
2371+.B "--print-param"
2372+option, it will print out something like the following:
2373+
2374+
2375+.nf
2376+
2377+# This MySQL options file was generated by XtraBackup.
2378+[mysqld]
2379+datadir = /data/mysql/
2380+innodb_data_home_dir = /data/innodb/
2381+innodb_data_file_path = ibdata1:10M:autoextend
2382+innodb_log_group_home_dir = /data/innodb-logs/
2383+
2384+.fi
2385+
2386+You can redirect this output into a file in the target directory of the backup.
2387+
2388+.SS " Agreeing on the Source Directory "
2389+
2390+
2391+It's possible that the presence of a defaults file or other factors could cause
2392+.B "xtrabackup"
2393+to back up data from a different location than you expected. To prevent this, you can use
2394+.B "--print-param"
2395+to ask it where it will be copying data from. You can use the output to ensure that
2396+.B "xtrabackup"
2397+and your script are working on the same dataset.
2398+
2399+.SS " Log Streaming "
2400+
2401+
2402+You can instruct
2403+.B "xtrabackup"
2404+to omit copying data files, and simply stream the log file to its standard output instead with
2405+.B "--log-stream"
2406+. This automatically adds the
2407+.B "--suspend-at-end"
2408+option. Your script can then perform tasks such as streaming remote backups by piping the log files into an SSH connection and copying the data files to another server with a tool such as
2409+.B "rsync"
2410+or
2411+.B "tar4ibd"
2412+.
2413+
2414+.SH " XtraBackup Exit Codes "
2415+
2416+
2417+The
2418+.B "xtrabackup"
2419+binary exits with the traditional success value of 0 after a backup when no error occurs. If an error occurs during the backup, the exit value is 1.
2420+
2421+In certain cases, the exit value can be something other than 0 or 1, due to the command-line option code included from the MySQL libraries. An unknown command-line option, for example, will cause an exit code of 255.
2422+
2423+When an error happens in the
2424+.B "main()"
2425+function of
2426+.B "xtrabackup.c"
2427+, when
2428+.B "xtrabackup"
2429+is preparing to perform the backup, the exit code is -1. This is usually because of a missing or wrong command-line option, failure to open a file or directory that the user specified as a command-line option, or similar. This behavior is changed in xtrabackup 1.4 and later, so it always returns 0 or 1. (However, the MySQL libraries might still exit with a code of 255.)
2430+
2431+.SH " Implementation Details "
2432+
2433+
2434+This page contains notes on various internal aspects of the
2435+.B "xtrabackup"
2436+tool's operation.
2437+
2438+.SS " File Permissions "
2439+
2440+
2441+
2442+.B "xtrabackup"
2443+opens the source data files in read-write mode, although it does not modify the files. This means that you must run
2444+.B "xtrabackup"
2445+as a user who has permission to write the data files. The reason for opening the files in read-write mode is that
2446+.B "xtrabackup"
2447+uses the embedded InnoDB libraries to open and read the files, and InnoDB opens them in read-write mode because it normally assumes it is going to write to them.
2448+
2449+.SS " Tuning the OS Buffers "
2450+
2451+
2452+Because
2453+.B "xtrabackup"
2454+reads large amounts of data from the filesystem, it uses
2455+.B "posix_fadvise()"
2456+where possible, to instruct the operating system not to try to cache the blocks it reads from disk. Without this hint, the operating system would prefer to cache the blocks, assuming that
2457+.B "xtrabackup"
2458+is likely to need them again, which is not the case. Caching such large files can place pressure on the operating system's virtual memory and cause other processes, such as the database server, to be swapped out. The
2459+.B "xtrabackup"
2460+tool avoids this with the following hint on both the source and destination files:
2461+
2462+ posix_fadvise(file, 0, 0, POSIX_FADV_DONTNEED)
2463+
2464+In addition,
2465+.B "xtrabackup"
2466+asks the operating system to perform more aggressive read-ahead optimizations on the source files:
2467+
2468+ posix_fadvise(file, 0, 0, POSIX_FADV_SEQUENTIAL)
2469+
2470+.SS " Copying Data Files "
2471+
2472+
2473+When copying the data files to the target directory,
2474+.B "xtrabackup"
2475+reads and writes 1MB of data at a time. This is not configurable. When copying the log file,
2476+.B "xtrabackup"
2477+reads and writes 512 bytes at a time. This is also not possible to configure, and matches InnoDB's behavior.
2478+
2479+After reading from the files,
2480+.B "xtrabackup"
2481+iterates over the 1MB buffer a page at a time, and checks for page corruption on each page with InnoDB's
2482+.B "buf_page_is_corrupted()"
2483+function. If the page is corrupt, it re-reads and retries up to 10 times for each page. It skips this check on the doublewrite buffer.
2484+.SH "AUTHOR"
2485+Percona Inc. http://www.percona.com/
2486+.SH "REPORTING BUGS"
2487+Report bugs to https://bugs.launchpad.net/percona-xtrabackup/+filebug
2488+.SH "LICENCE"
2489+GPL version 2
2490+
2491
2492=== added file 'plugin/innobase/xtrabackup/innobackupex'
2493--- plugin/innobase/xtrabackup/innobackupex 1970-01-01 00:00:00 +0000
2494+++ plugin/innobase/xtrabackup/innobackupex 2011-03-31 06:44:38 +0000
2495@@ -0,0 +1,2543 @@
2496+#!/usr/bin/perl -w
2497+#
2498+# A script for making backups of InnoDB and MyISAM tables, indexes and .frm
2499+# files.
2500+#
2501+# Copyright 2003, 2009 Innobase Oy and Percona Inc 2009-2011. All Rights Reserved.
2502+#
2503+
2504+use strict;
2505+use Getopt::Long;
2506+use File::Spec;
2507+use Pod::Usage qw(pod2usage);
2508+use POSIX "strftime";
2509+use POSIX ":sys_wait_h";
2510+use POSIX "tmpnam";
2511+use FileHandle;
2512+use File::Basename;
2513+use English qw(-no_match_vars);
2514+
2515+# version of this script
2516+my $innobackup_version = '1.5.1-xtrabackup';
2517+my $innobackup_script = basename($0);
2518+
2519+# copyright notice
2520+my $copyright_notice =
2521+"InnoDB Backup Utility v${innobackup_version}; Copyright 2003, 2009 Innobase Oy
2522+and Percona Inc 2009-2011. All Rights Reserved.
2523+
2524+This software is published under
2525+the GNU GENERAL PUBLIC LICENSE Version 2, June 1991.
2526+
2527+";
2528+
2529+# required Perl version (5.005)
2530+my @required_perl_version = (5, 0, 5);
2531+my $required_perl_version_old_style = 5.005;
2532+
2533+# force flush after every write and print
2534+$| = 1;
2535+
2536+######################################################################
2537+# modifiable parameters
2538+######################################################################
2539+
2540+# maximum number of files in a database directory which are
2541+# separately printed when a backup is made
2542+my $backup_file_print_limit = 9;
2543+
2544+# timeout in seconds for a reply from mysql
2545+my $mysql_response_timeout = 900;
2546+
2547+# default compression level (this is an argument to ibbackup)
2548+my $default_compression_level = 1;
2549+
2550+# time in seconds after which a dummy query is sent to mysql server
2551+# in order to keep the database connection alive
2552+my $mysql_keep_alive_timeout = 1800;
2553+
2554+######################################################################
2555+# end of modifiable parameters
2556+######################################################################
2557+
2558+
2559+# command line options
2560+my $option_help = '';
2561+my $option_version = '';
2562+my $option_apply_log = '';
2563+my $option_redo_only = '';
2564+my $option_copy_back = '';
2565+my $option_include = '';
2566+my $option_databases = '';
2567+my $option_tables_file = '';
2568+my $option_throttle = '';
2569+my $option_sleep = '';
2570+my $option_compress = 999;
2571+my $option_uncompress = '';
2572+my $option_export = '';
2573+my $option_use_memory = '';
2574+my $option_mysql_password = '';
2575+my $option_mysql_user = '';
2576+my $option_mysql_port = '';
2577+my $option_mysql_socket = '';
2578+my $option_mysql_host = '';
2579+my $option_no_timestamp = '';
2580+my $option_slave_info = '';
2581+my $option_no_lock = '';
2582+my $option_ibbackup_binary = 'autodetect';
2583+
2584+my $option_defaults_file = '';
2585+my $option_incremental = '';
2586+my $option_incremental_basedir = '';
2587+my $option_incremental_dir = '';
2588+my $option_incremental_lsn = '';
2589+my $option_extra_lsndir = '';
2590+my $option_remote_host = '';
2591+my $option_stream = '';
2592+my $option_tmpdir = '';
2593+
2594+my $option_tar4ibd = '';
2595+my $option_force_tar = '';
2596+my $option_scp_opt = '-Cp -c arcfour';
2597+
2598+my $option_parallel = '';
2599+
2600+my $option_safe_slave_backup = '';
2601+my $option_safe_slave_backup_timeout = 300;
2602+
2603+# name of the my.cnf configuration file
2604+#my $config_file = '';
2605+
2606+# root of the backup directory
2607+my $backup_root = '';
2608+
2609+# backup directory pathname
2610+my $backup_dir = '';
2611+
2612+# name of the ibbackup suspend-at-end file
2613+my $suspend_file = '';
2614+
2615+# name of the temporary transaction log file during the backup
2616+my $tmp_logfile = '';
2617+
2618+# home directory of innoDB log files
2619+my $innodb_log_group_home_dir = '';
2620+
2621+# backup my.cnf file
2622+my $backup_config_file = '';
2623+
2624+# options from the options file
2625+my %config;
2626+
2627+# options from the backup options file
2628+#my %backup_config;
2629+
2630+# list of databases to be included in a backup
2631+my %databases_list;
2632+
2633+# list of tables to be included in a backup
2634+my %table_list;
2635+
2636+# prefix for output lines
2637+my $prefix = "$innobackup_script:";
2638+
2639+# process id of mysql client program (runs as a child process of this script)
2640+my $mysql_pid = '';
2641+
2642+# mysql server version string
2643+my $mysql_server_version = '';
2644+
2645+# name of the file where stderr of mysql process is directed
2646+my $mysql_stderr = 'stderr';
2647+
2648+# name of the file where stdout of mysql process is directed
2649+my $mysql_stdout = 'stdout';
2650+
2651+# name of the file where binlog position info is written
2652+my $binlog_info;
2653+
2654+# name of the file where slave info is written
2655+my $slave_info;
2656+
2657+# mysql binlog position as given by "SHOW MASTER STATUS" command
2658+my $mysql_binlog_position = '';
2659+
2660+# mysql master's binlog position as given by "SHOW SLAVE STATUS" command
2661+# run on a slave server
2662+my $mysql_slave_position = '';
2663+
2664+# time of the most recent mysql_check call. (value returned by time() function)
2665+my $mysql_last_access_time = 0;
2666+
2667+# process id of ibbackup program (runs as a child process of this script)
2668+my $ibbackup_pid = '';
2669+
2670+# a counter for numbering mysql connection checks
2671+my $hello_id = 0;
2672+
2673+# the request which has been sent to mysqld, but to which
2674+# mysqld has not yet replied. Empty string denotes that no
2675+# request has been sent to mysqld or that mysqld has replied
2676+# to all requests.
2677+my $current_mysql_request = '';
2678+
2679+# escape sequences for options files
2680+my %option_value_escapes = ('b' => "\b",
2681+ 't' => "\t",
2682+ 'n' => "\n",
2683+ 'r' => "\r",
2684+ "\\" => "\\",
2685+ 's' => ' ');
2686+
2687+# signal that is sent to child processes when they are killed
2688+my $kill_signal = 15;
2689+
2690+# current local time
2691+my $now;
2692+
2693+# incremental backup base directory
2694+my $incremental_basedir = '';
2695+
2696+my $src_name;
2697+my $dst_name;
2698+my $win = ($^O eq 'MSWin32' ? 1 : 0);
2699+my $CP_CMD = ($win eq 1 ? "copy /Y" : "cp -p");
2700+my $xtrabackup_binary_file = 'xtrabackup_binary';
2701+######################################################################
2702+# program execution begins here
2703+######################################################################
2704+
2705+# check command-line args
2706+check_args();
2707+
2708+# print program version and copyright
2709+print_version();
2710+
2711+# initialize global variables and perform some checks
2712+if ($option_copy_back) {
2713+ $option_ibbackup_binary = 'xtrabackup_51';
2714+} elsif ($option_apply_log) {
2715+ # Read XtraBackup version from backup dir
2716+ if (-e "$backup_dir/$xtrabackup_binary_file") {
2717+ # Read XtraBackup version from file
2718+ open XTRABACKUP_BINARY, "$backup_dir/$xtrabackup_binary_file"
2719+ or die "Cannot open file $backup_dir/$xtrabackup_binary_file: $!\n";
2720+ $option_ibbackup_binary = <XTRABACKUP_BINARY>;
2721+ close XTRABACKUP_BINARY;
2722+ }
2723+
2724+ else {
2725+ if( $option_ibbackup_binary eq "autodetect" ){
2726+ # Try to connect MySQL and get the version
2727+ print "option_ibbackup_binary is autodetect, trying to connect to MySQL\n";
2728+ my $options = get_mysql_options();
2729+ $mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ");
2730+ print "Connected to MySQL with pid $mysql_pid\n";
2731+ sleep 1;
2732+ if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
2733+ my $reason = `cat $mysql_stderr`;
2734+ $mysql_pid = '';
2735+ # Failed to connect to MySQL
2736+ die "Failed to connect to MySQL server to detect version.\nYou must set xtrabackup version to use with --ibbackup option.\nPossible values are xtrabackup_51 (for MySQL 5.0 and 5.1) or xtrabackup (for MySQL 5.1 with InnoDB plugin or Percona Server)\n";
2737+ }
2738+ else{
2739+ mysql_close();
2740+ print "Connected successfully\n";
2741+ $option_ibbackup_binary = set_xtrabackup_version();
2742+ }
2743+ }
2744+ }
2745+} else {
2746+ $option_ibbackup_binary = set_xtrabackup_version();
2747+}
2748+init();
2749+
2750+my $ibbackup_exit_code = 0;
2751+
2752+if ($option_copy_back) {
2753+ # copy files from backup directory back to their original locations
2754+ copy_back();
2755+} elsif ($option_apply_log) {
2756+ # expand data files in backup directory by applying log files to them
2757+ apply_log();
2758+} else {
2759+ # make a backup of InnoDB and MyISAM tables, indexes and .frm files.
2760+ $ibbackup_exit_code = backup();
2761+ open XTRABACKUP_BINARY, "> $backup_dir/$xtrabackup_binary_file"
2762+ or die "Cannot open file $backup_dir/$xtrabackup_binary_file: $!\n";
2763+ print XTRABACKUP_BINARY $option_ibbackup_binary;
2764+ close XTRABACKUP_BINARY;
2765+}
2766+
2767+$now = current_time();
2768+
2769+if ($option_stream eq 'tar') {
2770+ print STDERR "$prefix You must use -i (--ignore-zeros) option for extraction of the tar stream.\n";
2771+}
2772+
2773+if ( $ibbackup_exit_code == 0 ) {
2774+ # program has completed successfully
2775+ print STDERR "$now $prefix completed OK!\n";
2776+}
2777+else {
2778+ print STDERR "$now $prefix $option_ibbackup_binary failed! (exit code $ibbackup_exit_code) The backup may not be complete.\n";
2779+}
2780+
2781+exit $ibbackup_exit_code;
2782+
2783+######################################################################
2784+# end of program execution
2785+######################################################################
2786+
2787+
2788+#
2789+# print_version subroutine prints program version and copyright.
2790+#
2791+sub print_version {
2792+ printf(STDERR $copyright_notice);
2793+}
2794+
2795+
2796+#
2797+# usage subroutine prints instructions of how to use this program to stdout.
2798+#
2799+sub usage {
2800+ my $msg = shift || '';
2801+ pod2usage({ -msg => $msg, -verbose => 1});
2802+ return 0;
2803+}
2804+
2805+
2806+#
2807+# return current local time as string in form "070816 12:23:15"
2808+#
2809+sub current_time {
2810+ return strftime("%y%m%d %H:%M:%S", localtime());
2811+}
2812+
2813+
2814+#
2815+# Die subroutine kills all child processes and exits this process.
2816+# This subroutine takes the same argument as the built-in die function.
2817+# Parameters:
2818+# message string which is printed to stdout
2819+#
2820+sub Die {
2821+ my $message = shift;
2822+ my $extra_info = '';
2823+
2824+ # kill all child processes of this process
2825+ kill_child_processes();
2826+
2827+ if ($current_mysql_request) {
2828+ $extra_info = " while waiting for reply to MySQL request:" .
2829+ " '$current_mysql_request'";
2830+ }
2831+ die "$prefix Error: $message$extra_info";
2832+}
2833+
2834+
2835+#
2836+# backup subroutine makes a backup of InnoDB and MyISAM tables, indexes and
2837+# .frm files. It connects to the database server and runs ibbackup as a child
2838+# process.
2839+#
2840+sub backup {
2841+ my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
2842+
2843+ # check that we can connect to the database. This done by
2844+ # connecting, issuing a query, and closing the connection.
2845+ mysql_open();
2846+ mysql_check();
2847+ mysql_close();
2848+
2849+ # start ibbackup as a child process
2850+ start_ibbackup();
2851+
2852+ # wait for ibbackup to suspend itself
2853+ if (!$option_remote_host && !$option_stream) {
2854+ wait_for_ibbackup_suspend();
2855+ }
2856+
2857+ if (!$option_incremental) {
2858+ # connect to database
2859+ mysql_open();
2860+
2861+ if ( $option_safe_slave_backup ) {
2862+ wait_for_safe_slave();
2863+ }
2864+
2865+ # flush tables with read lock
2866+ mysql_check();
2867+ mysql_lockall() if !$option_no_lock;
2868+
2869+ }
2870+
2871+ # backup .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV and .opt files
2872+ backup_files();
2873+
2874+ # resume ibbackup and wait till it has finished
2875+ my $ibbackup_exit_code = resume_ibbackup();
2876+
2877+ if (!$option_incremental) {
2878+ # release read locks on all tables
2879+ mysql_unlockall() if !$option_no_lock;
2880+
2881+ if ( $option_safe_slave_backup ) {
2882+ print STDERR "$prefix: Starting slave SQL thread\n";
2883+ mysql_send('START SLAVE SQL_THREAD;');
2884+ }
2885+
2886+ # disconnect from database
2887+ mysql_close();
2888+ }
2889+
2890+ if ($option_remote_host) {
2891+ system("scp $option_scp_opt '$tmp_logfile' '$option_remote_host:$backup_dir/xtrabackup_logfile'")
2892+ and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_logfile': $!";
2893+ unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
2894+
2895+ system("scp $option_scp_opt '$orig_datadir/xtrabackup_checkpoints' '$option_remote_host:$backup_dir/xtrabackup_checkpoints'")
2896+ and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_checkpoints': $!";
2897+ unlink "$orig_datadir/xtrabackup_checkpoints" || Die "Failed to delete '$orig_datadir/xtrabackup_checkpoints': $!";
2898+ } elsif ($option_stream eq 'tar') {
2899+ system("cd $option_tmpdir; tar chf - xtrabackup_logfile")
2900+ and Die "Failed to stream 'xtrabackup_logfile': $!";
2901+ unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
2902+
2903+ system("cd $orig_datadir; tar chf - xtrabackup_checkpoints")
2904+ and Die "Failed to stream 'xtrabackup_checkpoints': $!";
2905+ unlink "$orig_datadir/xtrabackup_checkpoints" || Die "Failed to delete '$orig_datadir/xtrabackup_checkpoints': $!";
2906+ }
2907+
2908+ print STDERR "\n$prefix Backup created in directory '$backup_dir'\n";
2909+ if ($mysql_binlog_position) {
2910+ print STDERR "$prefix MySQL binlog position: $mysql_binlog_position\n";
2911+ }
2912+ if ($mysql_slave_position && $option_slave_info) {
2913+ print STDERR "$prefix MySQL slave binlog position: $mysql_slave_position\n";
2914+ }
2915+
2916+ return $ibbackup_exit_code;
2917+}
2918+
2919+
2920+#
2921+# are_equal_innodb_data_file_paths subroutine checks if the given
2922+# InnoDB data file option values are equal.
2923+# Parameters:
2924+# str1 InnoDB data file path option value
2925+# str2 InnoDB data file path option value
2926+# Return value:
2927+# 1 if values are equal
2928+# 0 otherwise
2929+#
2930+sub are_equal_innodb_data_file_paths {
2931+ my $str1 = shift;
2932+ my $str2 = shift;
2933+ my @array1 = split(/;/, $str1);
2934+ my @array2 = split(/;/, $str2);
2935+
2936+ if ($#array1 != $#array2) { return 0; }
2937+
2938+ for (my $i = 0; $i <= $#array1; $i++) {
2939+ my @def1 = split(/:/, $array1[$i]);
2940+ my @def2 = split(/:/, $array2[$i]);
2941+
2942+ if ($#def1 != $#def2) { return 0; }
2943+
2944+ for (my $j = 0; $j <= $#def1; $j++) {
2945+ if ($def1[$j] ne $def2[$j]) { return 0; }
2946+ }
2947+ }
2948+ return 1;
2949+}
2950+
2951+
2952+#
2953+# is_in_array subroutine checks if the given string is in the array.
2954+# Parameters:
2955+# str a string
2956+# array_ref a reference to an array of strings
2957+# Return value:
2958+# 1 if string is in the array
2959+# 0 otherwise
2960+#
2961+sub is_in_array {
2962+ my $str = shift;
2963+ my $array_ref = shift;
2964+
2965+ if (grep { $str eq $_ } @{$array_ref}) {
2966+ return 1;
2967+ }
2968+ return 0;
2969+}
2970+
2971+
2972+#
2973+# copy_back subroutine copies data and index files from backup directory
2974+# back to their original locations.
2975+#
2976+sub copy_back {
2977+ my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
2978+ my $orig_ibdata_dir =
2979+ get_option(\%config, 'mysqld', 'innodb_data_home_dir');
2980+ my $orig_innodb_data_file_path =
2981+ get_option(\%config, 'mysqld', 'innodb_data_file_path');
2982+ my $orig_iblog_dir =
2983+ get_option(\%config, 'mysqld', 'innodb_log_group_home_dir');
2984+ my $excluded_files =
2985+ '^(\.\.?|backup-my\.cnf|xtrabackup_logfile|mysql-std(err|out)|.*\.ibz)$';
2986+ my @ibdata_files;
2987+ my $iblog_files = '^ib_logfile.*$';
2988+ my $compressed_data_file = '.*\.ibz$';
2989+ my $file;
2990+ my $backup_innodb_data_file_path;
2991+ # check that original data directory exists
2992+ if (! -d $orig_datadir) {
2993+ Die "Original data directory '$orig_datadir' does not exist!";
2994+ }
2995+ # check that original InnoDB data directory exists
2996+ if (! -d $orig_ibdata_dir) {
2997+ Die "Original InnoDB data directory '$orig_ibdata_dir' does not exist!";
2998+ }
2999+ # check that original InnoDB log directory exists
3000+ if (! -d $orig_iblog_dir) {
3001+ Die "Original InnoDB log directory '$orig_iblog_dir' does not exist!";
3002+ }
3003+
3004+ # check that the original options file and the backup options file have
3005+ # the same value for "innodb_data_file_path" option
3006+ #$backup_innodb_data_file_path =
3007+ # get_option(\%backup_config, 'mysqld', 'innodb_data_file_path');
3008+ #if (!are_equal_innodb_data_file_paths($orig_innodb_data_file_path,
3009+ # $backup_innodb_data_file_path)
3010+ #) {
3011+ # Die "The value of 'innodb_data_file_path' option in the original "
3012+ # . "my.cnf file '$config_file' is different from the value "
3013+ # . "in the backup my.cnf file '$backup_config_file'.\n(original: "
3014+ # . "'$orig_innodb_data_file_path')\n"
3015+ # . "(backup: '$backup_innodb_data_file_path')";
3016+ #}
3017+
3018+ # make a list of all ibdata files in the backup directory and all
3019+ # directories in the backup directory under which there are ibdata files
3020+ foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
3021+ my $path = (split(/:/,$a))[0];
3022+ my $filename = (split(/\/+/, $path))[-1];
3023+
3024+ # check that the backup data file exists
3025+ if (! -e "$backup_dir/$filename") {
3026+ if (-e "$backup_dir/${filename}.ibz") {
3027+ Die "Backup data file '$backup_dir/$filename' does not exist, but "
3028+ . "its compressed copy '${path}.ibz' exists. Check "
3029+ . "that you have run '$innobackup_script --apply-log --uncompress "
3030+ . "...' before attempting '$innobackup_script --copy-back ...' !";
3031+ } else {
3032+ Die "Backup data file '$backup_dir/$filename' does not exist.";
3033+ }
3034+ }
3035+
3036+ if (!is_in_array($filename, \@ibdata_files)) {
3037+ push(@ibdata_files, $filename);
3038+ }
3039+ }
3040+
3041+ # copy files from backup dir to their original locations
3042+
3043+ # copy files to original data directory
3044+ opendir(DIR, $backup_dir)
3045+ || Die "Can't open directory '$backup_dir': $!\n";
3046+ print STDERR "$prefix Starting to copy MyISAM tables, indexes,\n";
3047+ print STDERR "$prefix .MRG, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV, .opt, and .frm files\n";
3048+ print STDERR "$prefix in '$backup_dir'\n";
3049+ print STDERR "$prefix back to original data directory '$orig_datadir'\n";
3050+ while (defined($file = readdir(DIR))) {
3051+ if ($file =~ /$excluded_files/) { next; }
3052+ if (is_in_array($file, \@ibdata_files)) { next; }
3053+ if ($file =~ /$iblog_files/) { next; }
3054+ if (-d "$backup_dir/$file") {
3055+ my $subdir = "$backup_dir/$file";
3056+ my $file2;
3057+
3058+ print STDERR "$prefix Copying directory '$subdir'\n";
3059+ if (! -x "\"".escape_path("$orig_datadir/$file")."\"") {
3060+ system("mkdir \"".escape_path("$orig_datadir/$file")."\"")
3061+ and Die "Failed to create directory "
3062+ . "'$orig_datadir/$file' : $!";
3063+ }
3064+ opendir(SUBDIR, "$subdir")
3065+ || Die "Can't open directory '$subdir': $!\n";
3066+ while (defined($file2 = readdir(SUBDIR))) {
3067+ if (-d "$subdir/$file2") { next; }
3068+ if ($file2 =~ /$compressed_data_file/) { next; }
3069+ $src_name = escape_path("$subdir/$file2");
3070+ $dst_name = escape_path("$orig_datadir/$file");
3071+ system("$CP_CMD \"$src_name\" \"$dst_name\"")
3072+ and Die "Failed to copy file '$file': $!";
3073+ }
3074+ closedir(SUBDIR);
3075+ } else {
3076+ print STDERR "$prefix Copying file " .
3077+ "'$backup_dir/$file'\n";
3078+ $src_name = escape_path("$backup_dir/$file");
3079+ $dst_name = escape_path("$orig_datadir");
3080+ system("$CP_CMD \"$src_name\" \"$dst_name\"")
3081+ and Die "Failed to copy file '$file': $!";
3082+ }
3083+ }
3084+ closedir(DIR);
3085+
3086+ # copy InnoDB data files to original InnoDB data directory
3087+ print STDERR "\n$prefix Starting to copy InnoDB tables and indexes\n";
3088+ print STDERR "$prefix in '$backup_dir'\n";
3089+ print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n";
3090+ foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
3091+ # get the relative pathname of a data file
3092+ my $path = (split(/:/,$a))[0];
3093+ my $filename = (split(/\/+/, $path))[-1];
3094+ print STDERR "$prefix Copying file '$backup_dir/$filename'\n";
3095+ $src_name = escape_path("$backup_dir/$filename");
3096+ $dst_name = escape_path("$orig_ibdata_dir/$path");
3097+ system("$CP_CMD \"$src_name\" \"$dst_name\"")
3098+ and Die "Failed to copy file '$filename': $!";
3099+ }
3100+
3101+ # copy InnoDB log files to original InnoDB log directory
3102+ opendir(DIR, $backup_dir)
3103+ || Die "Can't open directory '$backup_dir': $!\n";
3104+ print STDERR "\n$prefix Starting to copy InnoDB log files\n";
3105+ print STDERR "$prefix in '$backup_dir'\n";
3106+ print STDERR "$prefix back to original InnoDB log directory '$orig_iblog_dir'\n";
3107+ while (defined($file = readdir(DIR))) {
3108+ if ($file =~ /$iblog_files/ && -f "$backup_dir/$file") {
3109+ print STDERR "$prefix Copying file '$backup_dir/$file'\n";
3110+ $src_name = escape_path("$backup_dir/$file");
3111+ $dst_name = escape_path("$orig_iblog_dir");
3112+ system("$CP_CMD \"$src_name\" \"$dst_name\"")
3113+ and Die "Failed to copy file '$file': $!";
3114+ }
3115+ }
3116+ closedir(DIR);
3117+
3118+ print STDERR "$prefix Finished copying back files.\n\n";
3119+}
3120+
3121+
3122+#
3123+# apply_log subroutine prepares a backup for starting database server
3124+# on the backup. It applies InnoDB log files to the InnoDB data files.
3125+#
3126+sub apply_log {
3127+ my $rcode;
3128+ my $cmdline = '';
3129+ my $options = '';
3130+
3131+ if ($option_defaults_file) {
3132+ $options = $options . " --defaults-file=\"$option_defaults_file\" ";
3133+ }
3134+
3135+ $options = $options . "--prepare --target-dir=$backup_dir";
3136+
3137+ if ($option_uncompress) {
3138+ $options = $options . ' --uncompress';
3139+ }
3140+ if ($option_export) {
3141+ $options = $options . ' --export';
3142+ }
3143+ if ($option_redo_only) {
3144+ $options = $options . ' --apply-log-only';
3145+ }
3146+ if ($option_use_memory) {
3147+ $options = $options . " --use-memory=$option_use_memory";
3148+ }
3149+
3150+ if ($option_incremental_dir) {
3151+ $options = $options . " --incremental-dir=$option_incremental_dir";
3152+ }
3153+
3154+ # run ibbackup as a child process
3155+ $cmdline = "$option_ibbackup_binary $options";
3156+ $now = current_time();
3157+ print STDERR "\n$now $prefix Starting ibbackup with command: $cmdline\n\n";
3158+ $rcode = system("$cmdline");
3159+ if ($rcode) {
3160+ # failure
3161+ Die "\n$prefix ibbackup failed";
3162+ }
3163+
3164+ # We should not create ib_logfile files if we prepare for following incremental applies
3165+ # Also we do not prepare ib_logfile if we applied incremental changes
3166+ if (!( ($option_redo_only) or ($option_incremental_dir))) {
3167+ $now = current_time();
3168+ print STDERR "\n$now $prefix Restarting xtrabackup with command: $cmdline\nfor creating ib_logfile*\n\n";
3169+ $rcode = system("$cmdline");
3170+ if ($rcode) {
3171+ # failure
3172+ Die "\n$prefix xtrabackup (2nd execution) failed";
3173+ }
3174+ }
3175+}
3176+
3177+
3178+#
3179+# wait_for_ibbackup_suspend subroutine waits until ibbackup has suspended
3180+# itself.
3181+#
3182+sub wait_for_ibbackup_suspend {
3183+ print STDERR "$prefix Waiting for ibbackup (pid=$ibbackup_pid) to suspend\n";
3184+ print STDERR "$prefix Suspend file '$suspend_file'\n\n";
3185+ for (;;) {
3186+ sleep 2;
3187+ last if -e $suspend_file;
3188+
3189+ # check that ibbackup child process is still alive
3190+ if ($ibbackup_pid == waitpid($ibbackup_pid, &WNOHANG)) {
3191+ $ibbackup_pid = '';
3192+ Die "ibbackup child process has died";
3193+ }
3194+ }
3195+ $now = current_time();
3196+ print STDERR "\n$now $prefix Continuing after ibbackup has suspended\n";
3197+}
3198+
3199+
3200+#
3201+# resume_ibbackup subroutine signals ibbackup to complete its execution
3202+# by deleting the 'ibbackup_suspended' file.
3203+#
3204+sub resume_ibbackup {
3205+ print STDERR "$prefix Resuming ibbackup\n\n";
3206+ unlink $suspend_file || Die "Failed to delete '$suspend_file': $!";
3207+
3208+ # wait for ibbackup to finish
3209+ waitpid($ibbackup_pid, 0);
3210+ $ibbackup_pid = '';
3211+ return $CHILD_ERROR >> 8;
3212+}
3213+
3214+
3215+#
3216+# start_ibbackup subroutine spawns a child process running ibbackup
3217+# program for backing up InnoDB tables and indexes.
3218+#
3219+sub start_ibbackup {
3220+ my $options = '';
3221+ my $cmdline = '';
3222+ my $pid = undef;
3223+
3224+ if ($option_defaults_file) {
3225+ $options = $options . " --defaults-file=\"$option_defaults_file\" ";
3226+ }
3227+
3228+ $options = $options . "--backup --suspend-at-end";
3229+
3230+ if (!$option_remote_host && !$option_stream) {
3231+ $options = $options . " --target-dir=$backup_dir";
3232+ } else {
3233+ #(datadir) for 'xtrabackup_suspended' and 'xtrabackup_checkpoints'
3234+ $options = $options . " --log-stream --target-dir=./";
3235+ }
3236+
3237+ # prepare command line for running ibbackup
3238+ if ($option_throttle) {
3239+ $options = $options . " --throttle=$option_throttle";
3240+ }
3241+ if ($option_sleep) {
3242+ $options = $options . " --sleep=$option_sleep";
3243+ }
3244+ if ($option_compress) {
3245+ $options = $options . " --compress=$option_compress";
3246+ }
3247+ if ($option_use_memory) {
3248+ $options = $options . " --use-memory=$option_use_memory";
3249+ }
3250+ if ($option_include) {
3251+ $options = $options . " --tables='$option_include'";
3252+ }
3253+ if ($option_extra_lsndir) {
3254+ $options = $options . " --extra-lsndir='$option_extra_lsndir'";
3255+ }
3256+
3257+ if ($option_incremental) {
3258+ if($option_incremental_lsn) {
3259+ $options = $options . " --incremental-lsn='$option_incremental_lsn'";
3260+ } else {
3261+ $options = $options . " --incremental-basedir='$incremental_basedir'";
3262+ }
3263+ }
3264+
3265+ if ($option_tables_file) {
3266+ $options = $options . " --tables_file='$option_tables_file'";
3267+ }
3268+ if ($option_parallel) {
3269+ $options = $options. " --parallel=$option_parallel";
3270+ }
3271+ $cmdline = "$option_ibbackup_binary $options";
3272+
3273+ # run ibbackup as a child process
3274+ $now = current_time();
3275+ print STDERR "\n$now $prefix Starting ibbackup with command: $cmdline\n";
3276+ if (defined($pid = fork)) {
3277+ if ($pid) {
3278+ # parent process
3279+ $ibbackup_pid = $pid;
3280+
3281+ if($option_remote_host || $option_stream) {
3282+ #direct copy to remote
3283+ my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
3284+ my $orig_ibdata_dir =
3285+ get_option(\%config, 'mysqld', 'innodb_data_home_dir');
3286+ my $orig_innodb_data_file_path =
3287+ get_option(\%config, 'mysqld', 'innodb_data_file_path');
3288+ my $innodb_flush_method =
3289+ get_option(\%config, 'mysqld', 'innodb_flush_method');
3290+ my $innodb_use_odirect;
3291+ $innodb_use_odirect = 1 if $innodb_flush_method =~ m/O_DIRECT/i;
3292+
3293+ my $subdir;
3294+ my @list;
3295+
3296+ if($option_remote_host) {
3297+ if (system("ssh $option_remote_host test -e $backup_dir/ib_logfile0")
3298+ == 0) {
3299+ print STDERR "$prefix Remove $option_remote_host:$backup_dir/ib_logfile*\n";
3300+ system("ssh $option_remote_host rm $backup_dir/ib_logfile\*")
3301+ and Die "Failed to rm file '$backup_dir/ib_logfile*': $!";
3302+ }
3303+ }
3304+
3305+ wait_for_ibbackup_suspend();
3306+
3307+ #InnoDB data files from original InnoDB data directory
3308+ print STDERR "\n$prefix Starting to backup InnoDB tables and indexes\n";
3309+ if($option_remote_host) {
3310+ print STDERR "$prefix to '$backup_dir'\n";
3311+ }
3312+ print STDERR "$prefix from original InnoDB data directory '$orig_ibdata_dir'\n";
3313+ foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
3314+ my $path = (split(/:/,$a))[0];
3315+ $path=~s/([\$\\\" ])/\\$1/g;
3316+ if($option_remote_host) {
3317+ print STDERR "$prefix Backing up file '$orig_ibdata_dir/$path'\n";
3318+ system("scp $option_scp_opt '$orig_ibdata_dir/$path' '$option_remote_host:$backup_dir/$path'")
3319+ and Die "Failed to scp file '$path': $!";
3320+ } elsif($option_stream eq 'tar') {
3321+ my $ret = 0;
3322+ my $tarcmd;
3323+ print STDERR "$prefix Backing up as tar stream '$path'\n";
3324+ if (!$option_tar4ibd) {
3325+ $tarcmd = "tar chf - -b 32";
3326+ } else {
3327+ $tarcmd = "tar4ibd";
3328+ if ($innodb_use_odirect) {
3329+ $tarcmd = "$tarcmd -d";
3330+ }
3331+ $tarcmd = "$tarcmd -c";
3332+ }
3333+ $ret = system("cd $orig_ibdata_dir; $tarcmd $path") >> 8;
3334+ if ($ret == 1) {
3335+ print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
3336+ } elsif ($ret != 0) {
3337+ print STDERR "$prefix tar returned with exit code $ret.\n";
3338+ if ( -e "$orig_ibdata_dir/$path" ) {
3339+ Die "Failed to stream '$orig_ibdata_dir/$path': $!";
3340+ }
3341+ else {
3342+ print STDERR "$prefix Ignoring nonexistent file '$orig_ibdata_dir/$path'.\n";
3343+ }
3344+ }
3345+ }
3346+ }
3347+
3348+ #copy *.ibd files
3349+ opendir(DIR, $orig_datadir)
3350+ || Die "Can't open directory '$orig_datadir': $!\n";
3351+ while (defined($subdir = readdir(DIR))) {
3352+ my $print_each_file = 0;
3353+ my $file_c;
3354+ my $file;
3355+ if ($subdir eq '.' || $subdir eq '..') { next; }
3356+ next unless -d "$orig_datadir/$subdir";
3357+ next unless check_if_required($subdir);
3358+
3359+ @list = glob("$orig_datadir/$subdir/" . '*.ibd');
3360+
3361+ $file_c = @list;
3362+ if ($file_c <= $backup_file_print_limit) {
3363+ $print_each_file = 1;
3364+ } else {
3365+ print STDERR "$prefix Backing up files " .
3366+ "'$orig_datadir/$subdir/*.ibd' ($file_c files)\n";
3367+ }
3368+ foreach $file (@list) {
3369+ next unless check_if_required($subdir, $file);
3370+ if($option_include) {
3371+ my $table_name;
3372+
3373+ $table_name = substr($file, rindex($file, '/'));
3374+ $table_name = substr($table_name, 1, rindex($table_name, '.') - 1);
3375+ $table_name = $subdir . "." . $table_name;
3376+
3377+ if (!($table_name =~ /$option_include/)) {
3378+ print STDERR "'$file' is skipped.\n";
3379+ next;
3380+ }
3381+ }
3382+
3383+ if ($print_each_file) {
3384+ print STDERR "$prefix Backing up file '$file'\n";
3385+ }
3386+ if($option_remote_host) {
3387+ if (system("ssh $option_remote_host test -e $backup_dir/$subdir")
3388+ != 0) {
3389+ system("ssh $option_remote_host mkdir $backup_dir/$subdir");
3390+ }
3391+ system("scp $option_scp_opt '$file' '$option_remote_host:$backup_dir/$subdir/'")
3392+ and Die "Failed to scp file '$file': $!";
3393+ } elsif($option_stream eq 'tar') {
3394+ my $ret = 0;
3395+ my $file_name = substr($file, rindex($file, '/') + 1);
3396+ $file_name=~s/([\$\\\" ])/\\$1/g;
3397+ if (!$option_tar4ibd) {
3398+ $ret = system("cd $orig_datadir; tar chf - -b 32 $subdir/$file_name") >> 8;
3399+ } else {
3400+ $ret = system("cd $orig_datadir; tar4ibd -c $subdir/$file_name") >> 8;
3401+ }
3402+ if ($ret == 1) {
3403+ print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
3404+ } elsif ($ret != 0) {
3405+ print STDERR "$prefix tar returned with exit code $ret.\n";
3406+ if ( -e "$orig_datadir/$subdir/$file_name" ) {
3407+ Die "Failed to stream '$orig_datadir/$subdir/$file_name': $!";
3408+ }
3409+ else {
3410+ print STDERR "$prefix Ignoring nonexistent file '$orig_datadir/$subdir/$file_name'.\n";
3411+ }
3412+ }
3413+ }
3414+ }
3415+ }
3416+ closedir(DIR);
3417+ }
3418+ } else {
3419+ if($option_remote_host || $option_stream) {
3420+ open(STDOUT, "> $tmp_logfile")
3421+ || Die "Failed to open file '$tmp_logfile': $!"
3422+ }
3423+
3424+ # child process
3425+ exec($cmdline) || Die "Failed to exec ibbackup: $!";
3426+ }
3427+ } else {
3428+ Die "failed to fork ibbackup child process: $!";
3429+ }
3430+}
3431+
3432+
3433+#
3434+# get_mysql_options subroutine returns the options to mysql client program
3435+# as a string. The options are determined from the options given by the
3436+# user to innobackup.
3437+#
3438+sub get_mysql_options {
3439+ my $options = '';
3440+
3441+ # this option has to be first
3442+ if ($option_defaults_file) {
3443+ $options = "$options --defaults-file='$option_defaults_file'";
3444+ }
3445+
3446+ if ($option_mysql_password) {
3447+ $options = "$options --password='$option_mysql_password'";
3448+ }
3449+ if ($option_mysql_user) {
3450+ $options = "$options --user='$option_mysql_user'";
3451+ }
3452+ if ($option_mysql_host) {
3453+ $options = "$options --host='$option_mysql_host'";
3454+ }
3455+ if ($option_mysql_port) {
3456+ $options = "$options --port='$option_mysql_port'";
3457+ }
3458+ if ($option_mysql_socket) {
3459+ $options = "$options --socket='$option_mysql_socket'";
3460+ }
3461+ $options = "$options --unbuffered --";
3462+ return $options;
3463+}
3464+
3465+
3466+#
3467+# mysql_open subroutine starts mysql as a child process with
3468+# a pipe connection.
3469+#
3470+sub mysql_open {
3471+ my $options = get_mysql_options();
3472+ # run mysql as a child process with a pipe connection
3473+ $now = current_time();
3474+ print STDERR "$now $prefix Starting mysql with options: $options\n";
3475+ $mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ") or Die "Failed to spawn mysql child process: $!";
3476+ MYSQL_WRITER->autoflush(1);
3477+ $now = current_time();
3478+ print STDERR "$now $prefix Connected to database with mysql child process (pid=$mysql_pid)\n";
3479+
3480+ mysql_check();
3481+}
3482+
3483+
3484+#
3485+# mysql_check subroutine checks that the connection to mysql child process
3486+# is ok.
3487+#
3488+sub mysql_check {
3489+ my $mysql_pid_copy = $mysql_pid;
3490+
3491+ # send a dummy query to mysql child process
3492+ $hello_id++;
3493+ my $hello_message = "innobackup hello $hello_id";
3494+ print MYSQL_WRITER "select '$hello_message';\n"
3495+ or Die "Connection to mysql child process failed: $!";
3496+
3497+ # wait for reply
3498+ eval {
3499+ local $SIG{ALRM} = sub { die "alarm clock restart" };
3500+ my $stdout = '';
3501+ my $stderr = '';
3502+ alarm $mysql_response_timeout;
3503+ while (index($stdout, $hello_message) < 0) {
3504+ sleep 2;
3505+ if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
3506+ my $reason = `cat $mysql_stderr`;
3507+ $mysql_pid = '';
3508+ die "mysql child process has died: $reason";
3509+ }
3510+ $stdout = `cat $mysql_stdout`;
3511+ $stderr = `cat $mysql_stderr | grep -v ^Warning`;
3512+ if ($stderr) {
3513+ # mysql has reported an error, do exit
3514+ die "mysql error: $stderr";
3515+ }
3516+ }
3517+ alarm 0;
3518+ };
3519+ if ($@ =~ /alarm clock restart/) {
3520+ Die "Connection to mysql child process (pid=$mysql_pid_copy) timedout."
3521+ . " (Time limit of $mysql_response_timeout seconds exceeded."
3522+ . " You may adjust time limit by editing the value of parameter"
3523+ . " \"\$mysql_response_timeout\" in this script.)";
3524+ } elsif ($@) { Die $@; }
3525+
3526+ $mysql_last_access_time = time();
3527+}
3528+
3529+
3530+#
3531+# mysql_keep_alive subroutine tries to keep connection to the mysqld database
3532+# server alive by sending a dummy query when the connection has been idle
3533+# for the specified time.
3534+#
3535+sub mysql_keep_alive {
3536+ if ((time() - $mysql_last_access_time) > $mysql_keep_alive_timeout) {
3537+ # too long idle, send a dummy query
3538+ mysql_check();
3539+ }
3540+}
3541+
3542+
3543+#
3544+# mysql_send subroutine send a request string to mysql child process.
3545+# This subroutine appends a newline character to the request and checks
3546+# that mysqld receives the query.
3547+# Parameters:
3548+# request request string
3549+#
3550+sub mysql_send {
3551+ my $request = shift;
3552+
3553+ $current_mysql_request = $request;
3554+ print MYSQL_WRITER "$request\n";
3555+ mysql_check();
3556+ $current_mysql_request = '';
3557+}
3558+
3559+
3560+#
3561+# mysql_close subroutine terminates mysql child process gracefully.
3562+#
3563+sub mysql_close {
3564+ print MYSQL_WRITER "quit\n";
3565+ $now = current_time();
3566+ print STDERR "$now $prefix Connection to database server closed\n";
3567+ $mysql_pid = '';
3568+}
3569+
3570+
3571+#
3572+# write_binlog_info subroutine retrieves MySQL binlog position and
3573+# saves it in a file. It also prints it to stdout.
3574+#
3575+sub write_binlog_info {
3576+ my @lines;
3577+ my @info_lines = ();
3578+ my $position = '';
3579+ my $filename = '';
3580+
3581+ # get binlog position
3582+ mysql_send "SHOW MASTER STATUS;";
3583+
3584+ # get "show master status" output lines (2) from mysql output
3585+ file_to_array($mysql_stdout, \@lines);
3586+ foreach my $line (@lines) {
3587+ if ($line =~ m/innobackup hello/) {
3588+ # this is a hello message, ignore it
3589+ } else {
3590+ # this is output line from "show master status"
3591+ push(@info_lines, $line);
3592+ }
3593+ }
3594+
3595+ # write binlog info file
3596+ if (!defined $info_lines[1]) {
3597+ $info_lines[1] = "";
3598+ }
3599+ if (!$option_remote_host) {
3600+ open(FILE, ">$binlog_info") ||
3601+ Die "Failed to open file '$binlog_info': $!";
3602+ } else {
3603+ open(FILE, "| ssh $option_remote_host 'cat > $binlog_info'") ||
3604+ Die "Failed to open file '$option_remote_host:$binlog_info': $!";
3605+ }
3606+ print FILE "$info_lines[1]\n";
3607+ close(FILE);
3608+
3609+ if ($option_stream eq 'tar') {
3610+ system("cd $option_tmpdir; tar chf - xtrabackup_binlog_info")
3611+ and Die "Failed to stream 'xtrabackup_binlog_info': $!";
3612+ unlink $binlog_info || Die "Failed to delete '$binlog_info': $!";
3613+ }
3614+
3615+ # get the name of the last binlog file and position in it
3616+ ($filename, $position) = $info_lines[1] =~ /^\s*([^\s]+)\s+(.*)$/;
3617+
3618+ if (defined $filename && defined $position) {
3619+ $mysql_binlog_position = "filename '$filename', position $position";
3620+ } else {
3621+ $mysql_binlog_position = "filename '', position ";
3622+ }
3623+}
3624+
3625+
3626+#
3627+# write_slave_info subroutine retrieves MySQL binlog position of the
3628+# master server in a replication setup and saves it in a file. It
3629+# also saves it in $msql_slave_position variable.
3630+#
3631+sub write_slave_info {
3632+ my @lines;
3633+ my @info_lines;
3634+ my $position = '';
3635+ my $filename = '';
3636+ my $master= '';
3637+
3638+ # get slave status. Use single quotes here, otherwise
3639+ # \G is evaluated as a control character.
3640+ mysql_send 'SHOW SLAVE STATUS\G;';
3641+
3642+ # get output of the "show slave status" command from mysql output
3643+ # and extract binlog position of the master server
3644+ file_to_array($mysql_stdout, \@lines);
3645+ for (@lines) {
3646+ $master = $1 if /Master_Host:\s*(\S*)\s*$/;
3647+ $filename = $1 if /Master_Log_File:\s*(\S*)\s*$/;
3648+ $position = $1 if /Master_Log_Pos:\s*(\S*)\s*$/;
3649+ }
3650+
3651+ # print slave status to a file
3652+ if (!$option_remote_host) {
3653+ open(FILE, ">$slave_info") ||
3654+ Die "Failed to open file '$slave_info': $!";
3655+ } else {
3656+ open(FILE, "| ssh $option_remote_host 'cat > $slave_info'") ||
3657+ Die "Failed to open file '$option_remote_host:$slave_info': $!";
3658+ }
3659+ print FILE "CHANGE MASTER TO MASTER_LOG_FILE='$filename', MASTER_LOG_POS=$position\n";
3660+ close(FILE);
3661+
3662+ if ($option_stream eq 'tar') {
3663+ system("cd $option_tmpdir; tar chf - xtrabackup_slave_info")
3664+ and Die "Failed to stream 'xtrabackup_slave_info': $!";
3665+ unlink $slave_info || Die "Failed to delete '$slave_info': $!";
3666+ }
3667+
3668+ $mysql_slave_position = "master host '$master', filename '$filename', position $position";
3669+}
3670+
3671+
3672+#
3673+# mysql_lockall subroutine puts a read lock on all tables in all databases.
3674+#
3675+sub mysql_lockall {
3676+ $now = current_time();
3677+ print STDERR "$now $prefix Starting to lock all tables...\n";
3678+
3679+ mysql_send "USE mysql;";
3680+# mysql_send "DROP TABLE IF EXISTS ibbackup_binlog_marker;";
3681+# if (compare_versions($mysql_server_version, '4.1.0') == -1) {
3682+# # MySQL server version is 4.0 or older, ENGINE keyword not supported
3683+# mysql_send "CREATE TABLE ibbackup_binlog_marker(a INT) TYPE=INNODB;";
3684+# } else {
3685+# # MySQL server version is 4.1 or newer, use ENGINE keyword
3686+# mysql_send "CREATE TABLE ibbackup_binlog_marker(a INT) ENGINE=INNODB;";
3687+# }
3688+ mysql_send "SET AUTOCOMMIT=0;";
3689+# mysql_send "INSERT INTO ibbackup_binlog_marker VALUES (1);";
3690+ if (compare_versions($mysql_server_version, '4.0.22') == 0
3691+ || compare_versions($mysql_server_version, '4.1.7') == 0) {
3692+ # MySQL server version is 4.0.22 or 4.1.7
3693+ mysql_send "COMMIT;";
3694+ mysql_send "FLUSH TABLES WITH READ LOCK;";
3695+ } else {
3696+ # MySQL server version is other than 4.0.22 or 4.1.7
3697+ mysql_send "FLUSH TABLES WITH READ LOCK;";
3698+ mysql_send "COMMIT;";
3699+ }
3700+ write_binlog_info;
3701+ write_slave_info if $option_slave_info;
3702+
3703+ $now = current_time();
3704+ print STDERR "$now $prefix All tables locked and flushed to disk\n";
3705+}
3706+
3707+
3708+#
3709+# mysql_unlockall subroutine releases read locks on all tables in all
3710+# databases.
3711+#
3712+sub mysql_unlockall {
3713+ mysql_send "UNLOCK TABLES;";
3714+# mysql_send "DROP TABLE IF EXISTS ibbackup_binlog_marker;";
3715+
3716+ $now = current_time();
3717+ print STDERR "$now $prefix All tables unlocked\n";
3718+}
3719+
3720+
3721+#
3722+# catch_sigpipe subroutine is a signal handler for SIGPIPE.
3723+#
3724+sub catch_sigpipe {
3725+ my $rcode;
3726+
3727+ if ($mysql_pid && (-1 == ($rcode = waitpid($mysql_pid, &WNOHANG))
3728+ || $rcode == $mysql_pid)) {
3729+ my $reason = `cat $mysql_stderr`;
3730+ print STDERR "Pipe to mysql child process broken: $reason at";
3731+ system("date +'%H:%M:%S'");
3732+ exit(1);
3733+ } else {
3734+ Die "Broken pipe";
3735+ }
3736+}
3737+
3738+
3739+#
3740+# kill_child_processes subroutine kills all child processes of this process.
3741+#
3742+sub kill_child_processes {
3743+ if ($ibbackup_pid) {
3744+ kill($kill_signal, $ibbackup_pid);
3745+ $ibbackup_pid = '';
3746+ }
3747+
3748+ if ($mysql_pid) {
3749+ kill($kill_signal, $mysql_pid);
3750+ $mysql_pid = '';
3751+ }
3752+}
3753+
3754+
3755+#
3756+# require_external subroutine checks that an external program is runnable
3757+# via the shell. This is tested by calling the program with the
3758+# given arguments. It is checked that the program returns 0 and does
3759+# not print anything to stderr. If this check fails, this subroutine exits.
3760+# Parameters:
3761+# program pathname of the program file
3762+# args arguments to the program
3763+# pattern a string containing a regular expression for finding
3764+# the program version.
3765+# this pattern should contain a subpattern enclosed
3766+# in parentheses which is matched with the version.
3767+# version_ref a reference to a variable where the program version
3768+# string is returned. Example "2.0-beta2".
3769+#
3770+sub require_external {
3771+ my $program = shift;
3772+ my $args = shift;
3773+ my $pattern = shift;
3774+ my $version_ref = shift;
3775+ my @lines;
3776+ my $tmp_stdout = tmpnam();
3777+ my $tmp_stderr = tmpnam();
3778+ my $rcode;
3779+ my $error;
3780+
3781+ $rcode = system("$program $args >$tmp_stdout 2>$tmp_stderr");
3782+ if ($rcode) {
3783+ $error = $!;
3784+ }
3785+ my $stderr = `cat $tmp_stderr | grep -v ^Warning`;
3786+ unlink $tmp_stderr;
3787+ if ($stderr ne '') {
3788+ # failure
3789+ unlink $tmp_stdout;
3790+ Die "Couldn't run $program: $stderr";
3791+ } elsif ($rcode) {
3792+ # failure
3793+ unlink $tmp_stdout;
3794+ Die "Couldn't run $program: $error";
3795+ }
3796+
3797+ # success
3798+ my $stdout = `cat $tmp_stdout`;
3799+ unlink $tmp_stdout;
3800+ @lines = split(/\n|;/,$stdout);
3801+ print STDERR "$prefix Using $lines[0]\n";
3802+
3803+ # get version string from the first output line of the program
3804+ ${$version_ref} = '';
3805+ if ($lines[0] =~ /$pattern/) {
3806+ ${$version_ref} = $1;
3807+ }
3808+}
3809+
3810+
3811+# compare_versions subroutine compares two GNU-style version strings.
3812+# A GNU-style version string consists of three decimal numbers delimitted
3813+# by dots, and optionally followed by extra attributes.
3814+# Examples: "4.0.1", "4.1.1-alpha-debug".
3815+# Parameters:
3816+# str1 a GNU-style version string
3817+# str2 a GNU-style version string
3818+# Return value:
3819+# -1 if str1 < str2
3820+# 0 if str1 == str2
3821+# 1 is str1 > str2
3822+sub compare_versions {
3823+ my $str1 = shift;
3824+ my $str2 = shift;
3825+ my $extra1 = '';
3826+ my $extra2 = '';
3827+ my @array1 = ();
3828+ my @array2 = ();
3829+ my $i;
3830+
3831+ # remove possible extra attributes
3832+ ($str1, $extra1) = $str1 =~ /^([0-9.]*)(.*)/;
3833+ ($str2, $extra2) = $str2 =~ /^([0-9.]*)(.*)/;
3834+
3835+ # split "dotted" decimal number string into an array
3836+ @array1 = split('\.', $str1);
3837+ @array2 = split('\.', $str2);
3838+
3839+ # compare in lexicographic order
3840+ for ($i = 0; $i <= $#array1 && $i <= $#array2; $i++) {
3841+ if ($array1[$i] < $array2[$i]) {
3842+ return -1;
3843+ } elsif ($array1[$i] > $array2[$i]) {
3844+ return 1;
3845+ }
3846+ }
3847+ if ($#array1 < $#array2) {
3848+ return -1;
3849+ } elsif ($#array1 > $#array2) {
3850+ return 1;
3851+ } else {
3852+ return 0;
3853+ }
3854+}
3855+
3856+
3857+#
3858+# init subroutine initializes global variables and performs some checks on the
3859+# system we are running on.
3860+#
3861+sub init {
3862+ my $mysql_version = '';
3863+ my $ibbackup_version = '';
3864+ my $run = '';
3865+
3866+ # print some instructions to the user
3867+ if (!$option_apply_log && !$option_copy_back) {
3868+ $run = 'backup';
3869+ } elsif ($option_copy_back) {
3870+ $run = 'copy-back';
3871+ } else {
3872+ $run = 'apply-log';
3873+ }
3874+ print STDERR "IMPORTANT: Please check that the $run run completes successfully.\n";
3875+ print STDERR " At the end of a successful $run run $innobackup_script\n";
3876+ print STDERR " prints \"completed OK!\".\n\n";
3877+
3878+ # check that MySQL client program and InnoDB Hot Backup program
3879+ # are runnable via shell
3880+ if (!$option_copy_back) {
3881+ # we are making a backup or applying log to backup
3882+ if (!$option_apply_log) {
3883+ # we are making a backup, we need mysql server
3884+ my $output = '';
3885+ my @lines = ();
3886+
3887+ # check that we have mysql client program
3888+ require_external('mysql', '--version', 'Ver ([^,]+)',
3889+ \$mysql_version);
3890+
3891+ # get mysql server version
3892+ my $options = get_mysql_options();
3893+ @lines = split('\n',
3894+ `mysql $options -e "select \@\@version"`);
3895+ $mysql_server_version = $lines[1];
3896+ print STDERR "$prefix Using mysql server version $mysql_server_version\n";
3897+ }
3898+ #require_external($option_ibbackup_binary, '--license',
3899+ # 'version (\S+)', \$ibbackup_version);
3900+ print STDERR "\n";
3901+
3902+ if ($option_include
3903+ && $ibbackup_version
3904+ && $ibbackup_version le "2.0") {
3905+ # --include option was given, but ibbackup is too
3906+ # old to support it
3907+ Die "--include option was given, but ibbackup is too old"
3908+ . " to support it. You must upgrade to InnoDB Hot Backup"
3909+ . " v2.0 in order to use --include option.\n";
3910+ }
3911+ }
3912+
3913+ # set signal handlers
3914+ $SIG{PIPE} = \&catch_sigpipe;
3915+
3916+ # read MySQL options file
3917+ #read_config_file($config_file, \%config);
3918+ read_config_file(\%config);
3919+
3920+ if(!$option_tmpdir) {
3921+ $option_tmpdir = get_option(\%config, 'mysqld', 'tmpdir');
3922+ }
3923+
3924+ # get innodb log home directory from options file
3925+ #$innodb_log_group_home_dir =
3926+ # get_option(\%config, 'mysqld', 'innodb_log_group_home_dir');
3927+
3928+ if (!$option_apply_log && !$option_copy_back) {
3929+ # we are making a backup, create a new backup directory
3930+ if (!$option_remote_host) {
3931+ $backup_dir = File::Spec->rel2abs(make_backup_dir());
3932+ } else {
3933+ $backup_dir = make_backup_dir();
3934+ }
3935+ print STDERR "$prefix Created backup directory $backup_dir\n";
3936+ if (!$option_remote_host && !$option_stream) {
3937+ $backup_config_file = $backup_dir . '/backup-my.cnf';
3938+ $suspend_file = $backup_dir . '/xtrabackup_suspended';
3939+ $mysql_stdout = $backup_dir . '/mysql-stdout';
3940+ $mysql_stderr = $backup_dir . '/mysql-stderr';
3941+ $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
3942+ $slave_info = $backup_dir . '/xtrabackup_slave_info';
3943+ } else {
3944+ $suspend_file = get_option(\%config, 'mysqld', 'datadir') . '/xtrabackup_suspended';
3945+ $tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
3946+ $mysql_stdout = $option_tmpdir . '/mysql-stdout';
3947+ $mysql_stderr = $option_tmpdir . '/mysql-stderr';
3948+ if ($option_stream) {
3949+ $backup_config_file = $option_tmpdir . '/backup-my.cnf';
3950+ $binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
3951+ $slave_info = $option_tmpdir . '/xtrabackup_slave_info';
3952+ } else {
3953+ $backup_config_file = $backup_dir . '/backup-my.cnf';
3954+ $binlog_info = $backup_dir . '/xtrabackup_binlog_info';
3955+ $slave_info = $backup_dir . '/xtrabackup_slave_info';
3956+ }
3957+ }
3958+ write_backup_config_file($backup_config_file);
3959+ } elsif ($option_copy_back) {
3960+ #$backup_config_file = $backup_dir . '/backup-my.cnf';
3961+ #read_config_file($backup_config_file, \%backup_config);
3962+ }
3963+}
3964+
3965+
3966+#
3967+# write_backup_config_file subroutine creates a backup options file for
3968+# ibbackup program. It writes to the file only those options that
3969+# are required by ibbackup.
3970+# Parameters:
3971+# filename name for the created options file
3972+#
3973+sub write_backup_config_file {
3974+ my $filename = shift;
3975+ my $innodb_data_file_path =
3976+ get_option(\%config, 'mysqld', 'innodb_data_file_path');
3977+ my $innodb_log_files_in_group =
3978+ get_option(\%config, 'mysqld', 'innodb_log_files_in_group');
3979+ my $innodb_log_file_size =
3980+ get_option(\%config, 'mysqld', 'innodb_log_file_size');
3981+ my $root;
3982+
3983+ my @array = split(/;/, $innodb_data_file_path);
3984+ for (my $i = 0; $i <= $#array; $i++) {
3985+ my @tmp = split(/\/+/, $array[$i]);
3986+ $array[$i] = $tmp[-1];
3987+ }
3988+ $innodb_data_file_path = join(";", @array);
3989+
3990+ if (!$option_remote_host) {
3991+ $root = $backup_dir;
3992+ open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
3993+ } else {
3994+ $root = `ssh $option_remote_host 'cd $backup_dir; pwd'`;
3995+ open(FILE, "| ssh $option_remote_host 'cat > $filename'")
3996+ || Die "Failed to open file '$option_remote_host:$filename': $!";
3997+ }
3998+
3999+ print FILE "# This MySQL options file was generated by $innobackup_script.\n\n" .
4000+ "# The MySQL server\n" .
4001+ "[mysqld]\n" .
4002+ "datadir=$root\n" .
4003+ "innodb_data_home_dir=$root\n" .
4004+ "innodb_data_file_path=$innodb_data_file_path\n" .
4005+ "innodb_log_group_home_dir=$root\n" .
4006+ "innodb_log_files_in_group=$innodb_log_files_in_group\n" .
4007+ "innodb_log_file_size=$innodb_log_file_size\n";
4008+ close(FILE);
4009+
4010+ if ($option_stream) {
4011+ my $filename_dir = dirname($filename);
4012+ my $filename_name = basename($filename);
4013+ if ($option_stream eq 'tar') {
4014+ system("cd $filename_dir; tar chf - $filename_name")
4015+ and Die "Failed to stream '$filename_name': $!";
4016+ }
4017+ unlink $filename || Die "Failed to delete '$filename': $!";
4018+ }
4019+}
4020+
4021+
4022+#
4023+# check_args subroutine checks command line arguments. If there is a problem,
4024+# this subroutine prints error message and exits.
4025+#
4026+sub check_args {
4027+ my $i;
4028+ my $rcode;
4029+ my $buf;
4030+ my $perl_version;
4031+
4032+ # check the version of the perl we are running
4033+ if (!defined $^V) {
4034+ # this perl is prior to 5.6.0 and uses old style version string
4035+ my $required_version = $required_perl_version_old_style;
4036+ if ($] lt $required_version) {
4037+ print STDERR "$prefix Warning: " .
4038+ "Your perl is too old! Innobackup requires\n";
4039+ print STDERR "$prefix Warning: perl $required_version or newer!\n";
4040+ }
4041+ }
4042+
4043+ if (@ARGV == 0) {
4044+ # no command line arguments
4045+ print STDERR "$prefix You must specify the backup directory.\n";
4046+ exit(1);
4047+ }
4048+
4049+ # read command line options
4050+ $rcode = GetOptions('compress:i' => \$option_compress,
4051+ 'help' => \$option_help,
4052+ 'version' => \$option_version,
4053+ 'throttle=i' => \$option_throttle,
4054+ 'sleep=i' => \$option_sleep,
4055+ 'apply-log' => \$option_apply_log,
4056+ 'redo-only' => \$option_redo_only,
4057+ 'copy-back' => \$option_copy_back,
4058+ 'include=s' => \$option_include,
4059+ 'databases=s' => \$option_databases,
4060+ 'tables-file=s', => \$option_tables_file,
4061+ 'use-memory=s' => \$option_use_memory,
4062+ 'uncompress' => \$option_uncompress,
4063+ 'export' => \$option_export,
4064+ 'password=s' => \$option_mysql_password,
4065+ 'user=s' => \$option_mysql_user,
4066+ 'host=s' => \$option_mysql_host,
4067+ 'port=s' => \$option_mysql_port,
4068+ 'slave-info' => \$option_slave_info,
4069+ 'socket=s' => \$option_mysql_socket,
4070+ 'no-timestamp' => \$option_no_timestamp,
4071+ 'defaults-file=s' => \$option_defaults_file,
4072+ 'incremental' => \$option_incremental,
4073+ 'incremental-basedir=s' => \$option_incremental_basedir,
4074+ 'incremental-lsn=s' => \$option_incremental_lsn,
4075+ 'incremental-dir=s' => \$option_incremental_dir,
4076+ 'extra-lsndir=s' => \$option_extra_lsndir,
4077+ 'remote-host=s' => \$option_remote_host,
4078+ 'stream=s' => \$option_stream,
4079+ 'tmpdir=s' => \$option_tmpdir,
4080+ 'no-lock' => \$option_no_lock,
4081+ 'ibbackup=s' => \$option_ibbackup_binary,
4082+ 'scpopt=s' => \$option_scp_opt,
4083+ 'force-tar', => \$option_force_tar,
4084+ 'parallel=i' => \$option_parallel,
4085+ 'safe-slave-backup' => \$option_safe_slave_backup,
4086+ 'safe-slave-backup-timeout' => $option_safe_slave_backup_timeout,
4087+ );
4088+
4089+ if (!$rcode) {
4090+ # failed to read options
4091+ print STDERR "$prefix Bad command line arguments\n";
4092+ exit(1);
4093+ }
4094+ if ($option_help) {
4095+ # print help text and exit
4096+ usage();
4097+ exit(0);
4098+ }
4099+ if ($option_version) {
4100+ # print program version and copyright
4101+ print_version();
4102+ exit(0);
4103+ }
4104+
4105+ if ($option_compress == 0) {
4106+ # compression level no specified, use default level
4107+ $option_compress = $default_compression_level;
4108+ }
4109+
4110+ if ($option_compress == 999) {
4111+ # compress option not given in the command line
4112+ $option_compress = 0;
4113+ }
4114+
4115+ if (@ARGV < 1) {
4116+ print STDERR "$prefix Missing command line argument\n";
4117+ exit(1);
4118+ } elsif (@ARGV > 1) {
4119+ print STDERR "$prefix Too many command line arguments\n";
4120+ exit(1);
4121+ }
4122+
4123+ if ($option_stream) {
4124+ if ($option_stream eq 'tar') {
4125+ if ( !$option_force_tar ) {
4126+ $option_tar4ibd = 'tar4ibd';
4127+ }
4128+ else {
4129+ print STDERR "Forcing tar instead of tar4ibd\n";
4130+ }
4131+ } elsif ($option_stream eq 'tar4ibd') {
4132+ $option_stream = 'tar';
4133+ $option_tar4ibd = 'tar4ibd';
4134+ } elsif ($option_stream eq 'cpio') {
4135+ print STDERR "$prefix --stream=cpio is not supported yet\n";
4136+ exit(1);
4137+ } else {
4138+ print STDERR "$prefix Unknown option --stream=$option_stream\n";
4139+ exit(1);
4140+ }
4141+ }
4142+
4143+ # get options file name
4144+ #$config_file = $ARGV[0];
4145+
4146+ if (!$option_apply_log && !$option_copy_back) {
4147+ # we are making a backup, get backup root directory
4148+ $backup_root = $ARGV[0];
4149+ if ($option_incremental) {
4150+ my @dirs = `ls -1 -t $backup_root`;
4151+ my $inc_dir = $dirs[0];
4152+ chomp($inc_dir);
4153+ if ($option_incremental_basedir) {
4154+ $incremental_basedir = $option_incremental_basedir;
4155+ } else {
4156+ $incremental_basedir = File::Spec->catfile($backup_root, $inc_dir);
4157+ }
4158+
4159+ #print STDERR "--incremental_basedir=$incremental_basedir\n";
4160+ #print STDERR "incremental backup is not supported for now.\n";
4161+ #exit(1);
4162+ }
4163+ } else {
4164+ # get backup directory
4165+ $backup_dir = File::Spec->rel2abs($ARGV[0]);
4166+ }
4167+
4168+ print STDERR "\n";
4169+
4170+ parse_databases_option_value();
4171+ parse_tables_file_option_value($option_tables_file);
4172+}
4173+
4174+
4175+#
4176+# make_backup_dir subroutine creates a new backup directory and returns
4177+# its name.
4178+#
4179+sub make_backup_dir {
4180+ my $dir;
4181+ my $innodb_data_file_path =
4182+ get_option(\%config, 'mysqld', 'innodb_data_file_path');
4183+
4184+ # create backup directory
4185+ $dir = $backup_root;
4186+ if ($option_stream) {
4187+ return $dir;
4188+ }
4189+
4190+ $dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())
4191+ unless $option_no_timestamp;
4192+ if (!$option_remote_host) {
4193+ mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
4194+ } else {
4195+ system("ssh $option_remote_host mkdir $dir");
4196+ }
4197+
4198+ # create subdirectories for ibdata files if needed
4199+# foreach my $a (split(/;/, $innodb_data_file_path)) {
4200+# my $path = (split(/:/,$a))[0];
4201+# my @relative_path = split(/\/+/, $path);
4202+# pop @relative_path;
4203+# if (@relative_path) {
4204+# # there is a non-trivial path from the backup directory
4205+# # to the directory of this backup ibdata file, check
4206+# # that all the directories in the path exist.
4207+# create_path_if_needed($dir, \@relative_path);
4208+# }
4209+# }
4210+
4211+ return $dir;
4212+}
4213+
4214+
4215+#
4216+# create_path_if_needed subroutine checks that all components
4217+# in the given relative path are directories. If the
4218+# directories do not exist, they are created.
4219+# Parameters:
4220+# root a path to the root directory of the relative pathname
4221+# relative_path a relative pathname (a reference to an array of
4222+# pathname components)
4223+#
4224+sub create_path_if_needed {
4225+ my $root = shift;
4226+ my $relative_path = shift;
4227+ my $path;
4228+
4229+ $path = $root;
4230+ foreach $a (@{$relative_path}) {
4231+ $path = $path . "/" . $a;
4232+ if (!$option_remote_host) {
4233+ if (! -d $path) {
4234+ # this directory does not exist, create it !
4235+ mkdir($path, 0777) || Die "Failed to create backup directory: $!";
4236+ }
4237+ } else {
4238+ if (system("ssh $option_remote_host test -d $path") != 0) {
4239+ system("ssh $option_remote_host mkdir $path");
4240+ }
4241+ }
4242+ }
4243+}
4244+
4245+
4246+#
4247+# remove_from_array subroutine removes excluded element from the array.
4248+# Parameters:
4249+# array_ref a reference to an array of strings
4250+# excluded a string to be excluded from the copy
4251+#
4252+sub remove_from_array {
4253+ my $array_ref = shift;
4254+ my $excluded = shift;
4255+ my @copy = ();
4256+ my $size = 0;
4257+
4258+ foreach my $str (@{$array_ref}) {
4259+ if ($str ne $excluded) {
4260+ $copy[$size] = $str;
4261+ $size = $size + 1;
4262+ }
4263+ }
4264+ @{$array_ref} = @copy;
4265+}
4266+
4267+
4268+#
4269+# backup_files subroutine copies .frm, .MRG, .MYD and .MYI files to
4270+# backup directory.
4271+#
4272+sub backup_files {
4273+ my $source_dir = get_option(\%config, 'mysqld', 'datadir');
4274+ my @list;
4275+ my $file;
4276+ my $database;
4277+ my $wildcard = '*.{frm,MYD,MYI,MRG,TRG,TRN,ARM,ARZ,CSM,CSV,opt,par}';
4278+
4279+ opendir(DIR, $source_dir)
4280+ || Die "Can't open directory '$source_dir': $!\n";
4281+ $now = current_time();
4282+ print STDERR "\n$now $prefix Starting to backup .frm, .MRG, .MYD, .MYI,\n";
4283+ print STDERR "$prefix .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV and .opt files in\n";
4284+ print STDERR "$prefix subdirectories of '$source_dir'\n";
4285+ # loop through all database directories
4286+ while (defined($database = readdir(DIR))) {
4287+ my $print_each_file = 0;
4288+ my $file_c;
4289+ my @scp_files;
4290+ # skip files that are not database directories
4291+ if ($database eq '.' || $database eq '..') { next; }
4292+ next unless -d "$source_dir/$database";
4293+ next unless check_if_required($database);
4294+
4295+ if (!$option_remote_host && !$option_stream) {
4296+ if (! -e "$backup_dir/$database") {
4297+ # create database directory for the backup
4298+ mkdir("$backup_dir/$database", 0777)
4299+ || Die "Couldn't create directory '$backup_dir/$database': $!";
4300+ }
4301+ } elsif ($option_remote_host) {
4302+ if (system("ssh $option_remote_host test -e $backup_dir/$database")
4303+ != 0) {
4304+ system("ssh $option_remote_host mkdir $backup_dir/$database");
4305+ }
4306+ }
4307+
4308+ # copy files of this database
4309+ opendir(DBDIR, "$source_dir/$database");
4310+ @list = grep(/\.(frm)|(MYD)|(MYI)|(MRG)|(TRG)|(TRN)|(ARM)|(ARZ)|(CSM)|(CSV)|(opt)|(par)$/, readdir(DBDIR));
4311+ closedir DBDIR;
4312+ $file_c = @list;
4313+ if ($file_c <= $backup_file_print_limit) {
4314+ $print_each_file = 1;
4315+ } else {
4316+ print STDERR "$prefix Backing up files " .
4317+ "'$source_dir/$database/$wildcard' ($file_c files)\n";
4318+ }
4319+ foreach $file (@list) {
4320+ # copying may take a long time, so we have to prevent
4321+ # mysql connection from timing out
4322+ mysql_keep_alive();
4323+ next unless check_if_required($database, $file);
4324+
4325+ if($option_include) {
4326+ if (!("$database.$file" =~ /$option_include/)) {
4327+ print STDERR "$database.$file is skipped because it does not match $option_include.\n";
4328+ next;
4329+ }
4330+ }
4331+
4332+
4333+ if ($print_each_file) {
4334+ print STDERR "$prefix Backing up file '$source_dir/$database/$file'\n";
4335+ }
4336+ if (!$option_remote_host && !$option_stream) {
4337+ $src_name = escape_path("$source_dir/$database/$file");
4338+ $dst_name = escape_path("$backup_dir/$database");
4339+ system("$CP_CMD \"$src_name\" \"$dst_name\"")
4340+ and Die "Failed to copy file '$file': $!";
4341+ } elsif ($option_remote_host) {
4342+ # Queue up files for one single scp per database.
4343+ push(@scp_files, "'$file'");
4344+ } elsif($option_stream eq 'tar') {
4345+ my $ret = 0;
4346+ my $file_name = substr($file, rindex($file, '/') + 1);
4347+ $file_name=~s/([\$\\\" ])/\\$1/g;
4348+ $ret = system("cd $source_dir; tar cf - $database/$file_name") >> 8;
4349+ if ($ret == 1) {
4350+ print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
4351+ } elsif ($ret != 0) {
4352+ print STDERR "$prefix tar returned with exit code $ret.\n";
4353+ Die "Failed to stream '$database/$file_name': $!";
4354+ }
4355+ }
4356+ }
4357+ if ($option_remote_host and @scp_files) {
4358+ my $scp_file_list = join(" ", map { "$source_dir/$database/$_" } @scp_files);
4359+ system("scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'")
4360+ and Die "Failed to execute \"scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'\": $!";
4361+ }
4362+ }
4363+ closedir(DIR);
4364+
4365+ $now = current_time();
4366+ print STDERR "$now $prefix Finished backing up .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSV, .CSM and .opt files\n\n";
4367+}
4368+
4369+
4370+#
4371+# file_to_array subroutine reads the given text file into an array and
4372+# stores each line as an element of the array. The end-of-line
4373+# character(s) are removed from the lines stored in the array.
4374+# Parameters:
4375+# filename name of a text file
4376+# lines_ref a reference to an array
4377+#
4378+sub file_to_array {
4379+ my $filename = shift;
4380+ my $lines_ref = shift;
4381+
4382+ open(FILE, $filename) || Die "can't open file '$filename': $!";
4383+ @{$lines_ref} = <FILE>;
4384+ close(FILE) || Die "can't close file '$filename': $!";
4385+
4386+ foreach my $a (@{$lines_ref}) {
4387+ chomp($a);
4388+ }
4389+}
4390+
4391+
4392+#
4393+# unescape_string subroutine expands escape sequences found in the string and
4394+# returns the expanded string. It also removes possible single or double quotes
4395+# around the value.
4396+# Parameters:
4397+# value a string
4398+# Return value:
4399+# a string with expanded escape sequences
4400+#
4401+sub unescape_string {
4402+ my $value = shift;
4403+ my $result = '';
4404+ my $offset = 0;
4405+
4406+ # remove quotes around the value if they exist
4407+ if (length($value) >= 2) {
4408+ if ((substr($value, 0, 1) eq "'" && substr($value, -1, 1) eq "'")
4409+ || (substr($value, 0, 1) eq '"' && substr($value, -1, 1) eq '"')) {
4410+ $value = substr($value, 1, -1);
4411+ }
4412+ }
4413+
4414+ # expand escape sequences
4415+ while ($offset < length($value)) {
4416+ my $pos = index($value, "\\", $offset);
4417+ if ($pos < 0) {
4418+ $pos = length($value);
4419+ $result = $result . substr($value, $offset, $pos - $offset);
4420+ $offset = $pos;
4421+ } else {
4422+ my $replacement = substr($value, $pos, 2);
4423+ my $escape_code = substr($value, $pos + 1, 1);
4424+ if (exists $option_value_escapes{$escape_code}) {
4425+ $replacement = $option_value_escapes{$escape_code};
4426+ }
4427+ $result = $result
4428+ . substr($value, $offset, $pos - $offset)
4429+ . $replacement;
4430+ $offset = $pos + 2;
4431+ }
4432+ }
4433+
4434+ return $result;
4435+}
4436+
4437+
4438+#
4439+# read_config_file subroutine reads MySQL options file and
4440+# returns the options in a hash containing one hash per group.
4441+# Parameters:
4442+# filename name of a MySQL options file
4443+# groups_ref a reference to hash variable where the read
4444+# options are returned
4445+#
4446+sub read_config_file {
4447+ #my $filename = shift;
4448+ my $groups_ref = shift;
4449+ my @lines ;
4450+ my $i;
4451+ my $group;
4452+ my $group_hash_ref;
4453+
4454+ my $cmdline = '';
4455+ my $options = '';
4456+
4457+ if ($option_defaults_file) {
4458+ $options = $options . " --defaults-file=\"$option_defaults_file\" ";
4459+ }
4460+
4461+ $options = $options . "--print-param";
4462+
4463+
4464+ # read file to an array, one line per element
4465+ #file_to_array($filename, \@lines);
4466+ $cmdline = "$option_ibbackup_binary $options";
4467+ @lines = `$cmdline`;
4468+
4469+ # classify lines and save option values
4470+ $group = 'default';
4471+ $group_hash_ref = {};
4472+ ${$groups_ref}{$group} = $group_hash_ref;
4473+ # this pattern described an option value which may be
4474+ # quoted with single or double quotes. This pattern
4475+ # does not work by its own. It assumes that the first
4476+ # opening parenthesis in this string is the second opening
4477+ # parenthesis in the full pattern.
4478+ my $value_pattern = q/((["'])([^\\\4]|(\\[^\4]))*\4)|([^\s]+)/;
4479+ for ($i = 0; $i < @lines; $i++) {
4480+ SWITCH: for ($lines[$i]) {
4481+ # comment
4482+ /^\s*(#|;)/
4483+ && do { last; };
4484+
4485+ # group
4486+ /^\s*\[(.*)\]/
4487+ && do {
4488+ $group = $1;
4489+ if (!exists ${$groups_ref}{$group}) {
4490+ $group_hash_ref = {};
4491+ ${$groups_ref}{$group} = $group_hash_ref;
4492+ } else {
4493+ $group_hash_ref = ${$groups_ref}{$group};
4494+ }
4495+ last;
4496+ };
4497+
4498+ # option
4499+ /^\s*([^\s=]+)\s*(#.*)?$/
4500+ && do {
4501+ ${$group_hash_ref}{$1} = '';
4502+ last;
4503+ };
4504+
4505+ # set-variable = option = value
4506+ /^\s*set-variable\s*=\s*([^\s=]+)\s*=\s*($value_pattern)\s*(#.*)?$/
4507+ && do { ${$group_hash_ref}{$1} = unescape_string($2); last; };
4508+
4509+ # option = value
4510+ /^\s*([^\s=]+)\s*=\s*($value_pattern)\s*(#.*)?$/
4511+ && do { ${$group_hash_ref}{$1} = unescape_string($2); last; };
4512+
4513+ # empty line
4514+ /^\s*$/
4515+ && do { last; };
4516+
4517+ # unknown
4518+ print("$prefix: Warning: Ignored unrecognized line ",
4519+ $i + 1,
4520+ " in options : '${lines[$i]}'\n"
4521+ );
4522+ }
4523+ }
4524+}
4525+
4526+
4527+#
4528+# get_option subroutine returns the value of given option in the config
4529+# structure. If option is missing, this subroutine calls exit.
4530+# Parameters:
4531+# config_ref a reference to a config data
4532+# group option group name
4533+# option_name name of the option
4534+# Return value:
4535+# option value as a string
4536+#
4537+sub get_option {
4538+ my $config_ref = shift;
4539+ my $group = shift;
4540+ my $option_name = shift;
4541+ my $group_hash_ref;
4542+
4543+ if (!exists $config{$group}) {
4544+ # no group
4545+ print STDERR "$prefix fatal error: no '$group' group in MySQL options\n";
4546+ print STDERR "$prefix fatal error: OR no 'datadir' option in group '$group' in MySQL options\n";
4547+ exit(1);
4548+ }
4549+
4550+ $group_hash_ref = ${$config_ref}{$group};
4551+ if (!exists ${$group_hash_ref}{$option_name}) {
4552+ # no option
4553+ print STDERR "$prefix fatal error: no '$option_name' option in group '$group' in MySQL options\n";
4554+ exit(1);
4555+ }
4556+
4557+ return ${$group_hash_ref}{$option_name};
4558+}
4559+
4560+# check_if_required subroutine returns 1 if the specified database and
4561+# table needs to be backed up.
4562+# Parameters:
4563+# $_[0] name of database to be checked
4564+# $_[1] full path of table file (This argument is optional)
4565+# Return value:
4566+# 1 if backup should be done and 0 if not
4567+#
4568+sub check_if_required {
4569+ my ( $db, $table_path ) = @_;
4570+ my $db_count = scalar keys %databases_list;
4571+ my $tbl_count = scalar keys %table_list;
4572+ my $filename;
4573+ my $table;
4574+
4575+ if ( $db_count == 0 && $tbl_count == 0 ) {
4576+ # No databases defined with --databases option, include all databases,
4577+ # and no tables defined with --tables-file option, include all tables.
4578+ return 1;
4579+ }
4580+ else {
4581+ if ( $table_path ) {
4582+ # get the last component in the table pathname
4583+ $filename = (reverse(split(/\//, $table_path)))[0];
4584+ # get name of the table by removing file suffix
4585+ $table = (split(/\./, $filename))[0];
4586+ }
4587+ }
4588+
4589+ # Filter for --databases.
4590+ if ( $db_count ) {
4591+ if (defined $databases_list{$db}) {
4592+ if (defined $table_path) {
4593+ my $db_hash = $databases_list{$db};
4594+ $db_count = keys %$db_hash;
4595+ if ($db_count > 0 && ! defined $databases_list{$db}->{$table}) {
4596+ # --databases option specified, but table is not included
4597+ return 0;
4598+ }
4599+ }
4600+ # include this database and table
4601+ return 1;
4602+ }
4603+ else {
4604+ # --databases option given, but database is not included
4605+ return 0;
4606+ }
4607+ }
4608+
4609+ # Filter for --tables-file.
4610+ if ( $tbl_count ) {
4611+ return 0 unless exists $table_list{$db};
4612+ return 0 if $table && !$table_list{$db}->{$table};
4613+ }
4614+
4615+ return 1; # backup the table
4616+}
4617+
4618+
4619+# parse_databases_option_value subroutine parses the value of
4620+# --databases option. If the option value begins with a slash
4621+# it is considered a pathname and the option value is read
4622+# from the file.
4623+#
4624+# This subroutine sets the global "databases_list" variable.
4625+#
4626+sub parse_databases_option_value {
4627+ my $item;
4628+
4629+ if ($option_databases =~ /^\//) {
4630+ # the value of the --databases option begins with a slash,
4631+ # the option value is pathname of the file containing
4632+ # list of databases
4633+ if (! -f $option_databases) {
4634+ Die "can't find file '$option_databases'";
4635+ }
4636+
4637+ # read from file the value of --databases option
4638+ my @lines;
4639+ file_to_array($option_databases, \@lines);
4640+ $option_databases = join(" ", @lines);
4641+ }
4642+
4643+ # mark each database or database.table definition in the
4644+ # global databases_list.
4645+ foreach $item (split(/\s/, $option_databases)) {
4646+ my $db = "";
4647+ my $table = "";
4648+ my %hash;
4649+
4650+ if ($item eq "") {
4651+ # ignore empty strings
4652+ next;
4653+ }
4654+
4655+ # get database and table names
4656+ if ($item =~ /(\S*)\.(\S*)/) {
4657+ # item is of the form DATABASE.TABLE
4658+ $db = $1;
4659+ $table = $2;
4660+ } else {
4661+ # item is database name, table is undefined
4662+ $db = $item;
4663+ }
4664+
4665+ if (! defined $databases_list{$db}) {
4666+ # create empty hash for the database
4667+ $databases_list{$db} = \%hash;
4668+ }
4669+ if ($table ne "") {
4670+ # add mapping table --> 1 to the database hash
4671+ my $h = $databases_list{$db};
4672+ $h->{$table} = 1;
4673+ }
4674+ }
4675+}
4676+
4677+# Parse the --tables-file file to determine which InnoDB tables
4678+# are backedup up. Only backedup tables have their .frm, etc.
4679+# files copied.
4680+sub parse_tables_file_option_value {
4681+ my ( $filename ) = @_;
4682+
4683+ return unless $filename;
4684+
4685+ open my $fh, '<', $filename;
4686+ if ( $fh ) {
4687+ while ( my $line = <$fh> ) {
4688+ chomp $line;
4689+ my ( $db, $tbl ) = $line =~ m/\s*([^\.]+)\.([^\.]+)\s*/;
4690+ if ( $db && $tbl ) {
4691+ $table_list{$db}->{$tbl} = 1;
4692+ print STDERR "$prefix $db.$tbl will be registerd to the list\n";
4693+ }
4694+ else {
4695+ warn "$prefix Invalid line in $filename: $line";
4696+ }
4697+ }
4698+ }
4699+ else {
4700+ warn "$prefix Cannot read --tables-file $filename: $OS_ERROR";
4701+ }
4702+
4703+ return;
4704+}
4705+
4706+sub escape_path {
4707+ my $str = shift;
4708+ if ($win eq 1) {
4709+ $str =~ s/\//\\/g;
4710+ $str =~ s/\\\\/\\/g;
4711+ }
4712+ else{
4713+ $str =~ s/\/\//\//g;
4714+ }
4715+ return $str;
4716+
4717+}
4718+
4719+sub set_xtrabackup_version {
4720+# Based on MySQL version choose correct binary
4721+# MySQL 5.0.* - xtrabackup_51
4722+# MySQL 5.1.* - xtrabackup_51
4723+# MySQL 5.1.* with InnoDB plugin - xtrabackup
4724+# Percona Server >= 11.0 - xtrabackup
4725+# MySQL 5.5.* - xtrabackup_55
4726+
4727+my @lines;
4728+my $var_version = '';
4729+my $var_innodb_version = '';
4730+my $ibbackup_binary;
4731+mysql_open();
4732+mysql_send "SHOW VARIABLES LIKE 'version'\\G";
4733+file_to_array($mysql_stdout, \@lines);
4734+for (@lines) {
4735+ $var_version = $1 if /Value:\s+(\S+)/;
4736+ }
4737+mysql_send "SHOW VARIABLES LIKE 'innodb_version'\\G";
4738+file_to_array($mysql_stdout, \@lines);
4739+for (@lines) {
4740+ $var_innodb_version = $1 if /Value:\s+(\S+)/;
4741+ }
4742+if($var_version =~ m/5\.0\.\d/){
4743+ $ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_51');
4744+}
4745+if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m//){
4746+ $ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_51');
4747+}
4748+if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+$/){
4749+ $ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
4750+}
4751+if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+-\d/){
4752+ $ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
4753+}
4754+if($var_version =~ m/5\.5\.\d/){
4755+ $ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_55');
4756+}
4757+mysql_close();
4758+return $ibbackup_binary;
4759+}
4760+
4761+# Wait until it's safe to backup a slave. Returns immediately if
4762+# the host isn't a slave. Currently there's only one check:
4763+# Slave_open_temp_tables has to be zero. Dies on timeout.
4764+sub wait_for_safe_slave {
4765+ my @lines;
4766+
4767+ my $host_is_slave = 0;
4768+ mysql_send 'SHOW SLAVE STATUS\G;';
4769+ file_to_array($mysql_stdout, \@lines);
4770+ foreach my $line ( @lines ) {
4771+ if ( $line =~ m/Read_Master_Log_Pos/ ) {
4772+ $host_is_slave = 1;
4773+ last;
4774+ }
4775+ }
4776+ if ( !$host_is_slave ) {
4777+ print STDERR "$prefix: Not checking slave open temp tables for --safe-slave-backup because host is not a slave\n";
4778+ return;
4779+ }
4780+
4781+ mysql_send 'STOP SLAVE SQL_THREAD;';
4782+
4783+ my $open_temp_tables = get_slave_open_temp_tables();
4784+ print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
4785+
4786+ return if $open_temp_tables == 0;
4787+
4788+ my $sleep_time = 3;
4789+ my $n_attempts = int($option_safe_slave_backup_timeout / $sleep_time) || 1;
4790+ while ( $n_attempts-- ) {
4791+ print STDERR "$prefix: Starting slave SQL thread, waiting $sleep_time seconds, then checking Slave_open_temp_tables again ($n_attempts attempts remaining)...\n";
4792+
4793+ mysql_send 'START SLAVE SQL_THREAD;';
4794+ sleep $sleep_time;
4795+ mysql_send 'STOP SLAVE SQL_THREAD;';
4796+
4797+ $open_temp_tables = get_slave_open_temp_tables();
4798+ print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
4799+ if ( !$open_temp_tables ) {
4800+ print STDERR "$prefix: Slave is safe to backup\n";
4801+ return;
4802+ }
4803+ }
4804+
4805+ Die "Slave_open_temp_tables did not become zero after waiting $option_safe_slave_backup_timeout seconds";
4806+}
4807+
4808+sub get_slave_open_temp_tables {
4809+ my @lines;
4810+ mysql_send 'SHOW STATUS LIKE "slave_open_temp_tables"\G;';
4811+ file_to_array($mysql_stdout, \@lines);
4812+ my $last_value;
4813+ for my $i ( 0..$#lines ) {
4814+ $last_value = $i + 1
4815+ if $lines[$i] =~ m/Variable_name: Slave_open_temp_tables/i;
4816+ }
4817+ Die "SHOW STATUS LIKE 'slave_open_temp_tables' did not return anything"
4818+ unless $last_value;
4819+
4820+ Die "Failed to get Slave_open_temp_tables from SHOW STATUS"
4821+ unless defined $lines[$last_value];
4822+
4823+ my ($n) = $lines[$last_value] =~ m/(\d+)/;
4824+ return $n;
4825+}
4826+
4827+=pod
4828+
4829+=head1 NAME
4830+
4831+innobackupex - Non-blocking backup tool for InnoDB, XtraDB and HailDB databases
4832+
4833+=head1 SYNOPOSIS
4834+
4835+innobackupex [--compress[=LEVEL]] [--include=REGEXP] [--user=NAME]
4836+ [--password=WORD] [--port=PORT] [--socket=SOCKET]
4837+ [--no-timestamp] [--ibbackup-binary=IBBACKUP-BINARY]
4838+ [--slave-info] [--stream=tar] [--force-tar]
4839+ [--scpopt=OPTIONS-FOR-SCP] [--defaults-file=MY.CNF]
4840+ [--databases=LIST] [--remote-host=HOSTNAME] [--no-lock]
4841+ [--tmpdir=DIRECTORY] [--tables-file=FILE]
4842+ [--incremental] [--incremental-basedir]
4843+ [--incremental-dir] [--incremental-lsn]
4844+ BACKUP-ROOT-DIR
4845+
4846+innobackupex --apply-log [--use-memory=MB] [--uncompress]
4847+ [--defaults-file=MY.CNF]
4848+ [--export] [--redo-only] [--ibbackup=IBBACKUP-BINARY]
4849+ BACKUP-DIR
4850+
4851+innobackupex --copy-back [--defaults-file=MY.CNF] BACKUP-DIR
4852+
4853+=head1 DESCRIPTION
4854+
4855+The first command line above makes a hot backup of a MySQL database.
4856+By default it creates a backup directory (named by the current date
4857+and time) in the given backup root directory. With the --no-timestamp
4858+option it does not create a time-stamped backup directory, but it puts
4859+the backup in the given directory (which must not exist). This
4860+command makes a complete backup of all MyISAM and InnoDB tables and
4861+indexes in all databases or in all of the databases specified with the
4862+--databases option. The created backup contains .frm, .MRG, .MYD,
4863+.MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, CSV, .opt, .par, and InnoDB data and log files.
4864+The MY.CNF options file defines the location of the database. This command
4865+connects to the MySQL server using the mysql client program, and runs
4866+xtrabackup as a child process.
4867+
4868+The --apply-log command prepares a backup for starting a MySQL
4869+server on the backup. This command recovers InnoDB data files as specified
4870+in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/xtrabackup_logfile,
4871+and creates new InnoDB log files as specified in BACKUP-DIR/backup-my.cnf.
4872+The BACKUP-DIR should be the path to a backup directory created by
4873+xtrabackup. This command runs xtrabackup as a child process, but it does not
4874+connect to the database server.
4875+
4876+The --copy-back command copies data, index, and log files
4877+from the backup directory back to their original locations.
4878+The MY.CNF options file defines the original location of the database.
4879+The BACKUP-DIR is the path to a backup directory created by xtrabackup.
4880+
4881+On success the exit code innobackupex is 0. A non-zero exit code
4882+indicates an error.
4883+
4884+
4885+=head1 OPTIONS
4886+
4887+=over
4888+
4889+=item --apply-log
4890+
4891+Prepare a backup in BACKUP-DIR by applying the transaction log file named "xtrabackup_logfile" located in the same directory. Also, create new transaction logs. The InnoDB configuration is read from the file "backup-my.cnf".
4892+
4893+=item --copy-back
4894+
4895+Copy all the files in a previously made backup from the backup directory to their original locations.
4896+
4897+=item --databases=LIST
4898+
4899+This option specifies the list of databases that innobackupex should back up. The option accepts a string argument. The list is of the form "databasename1[.table_name1] databasename2[.table_name2] . . .". If this option is not specified, all databases containing MyISAM and InnoDB tables will be backed up. Please make sure that --databases contains all of the InnoDB databases and tables, so that all of the innodb.frm files are also backed up. In case the list is very long, this can be specified in a file, and the full path of the file can be specified instead of the list. (See option --tables-file.)
4900+
4901+=item --defaults-file=[MY.CNF]
4902+
4903+This option specifies what file to read the default MySQL options from. The option accepts a string argument. It is also passed directly to xtrabackup's --defaults-file option. See the xtrabackup documentation for details.
4904+
4905+=item --export
4906+
4907+This option is passed directly to xtrabackup's --export option. It enables exporting individual tables for import into another server. See the xtrabackup documentation for details.
4908+
4909+=item --extra-lsndir=DIRECTORY
4910+
4911+This option specifies the directory in which to save an extra copy of the "xtrabackup_checkpoints" file. The option accepts a string argument. It is passed directly to xtrabackup's --extra-lsndir option. See the xtrabackup documentation for details.
4912+
4913+=item --force-tar
4914+
4915+This option forces the use of tar when creating a streamed backup, rather than tar4ibd, which is the default.
4916+
4917+=item --help
4918+
4919+This option displays a help screen and exits.
4920+
4921+=item --host=HOST
4922+
4923+This option specifies the host to use when connecting to the database server with TCP/IP. The option accepts a string argument. It is passed to the mysql child process without alteration. See mysql --help for details.
4924+
4925+=item --ibbackup-binary=IBBACKUP-BINARY
4926+
4927+This option specifies which xtrabackup binary should be used. The option accepts a string argument. IBBACKUP-BINARY should be the command used to run XtraBackup. The option can be useful if the xtrabackup binary is not in your search path or working directory. If this option is not specified, innobackupex attempts to determine the binary to use automatically. By default, "xtrabackup" is the command used. However, when option --copy-back is specified, "xtrabackup_51" is the command used. And when option --apply-log is specified, the binary is used whose name is in the file "xtrabackup_binary" in the backup directory, if that file exists.
4928+
4929+=item --include=REGEXP
4930+
4931+This option is a regular expression to be matched against table names in databasename.tablename format. It is passed directly to xtrabackup's --tables option. See the xtrabackup documentation for details.
4932+
4933+=item --incremental
4934+
4935+This option tells xtrabackup to create an incremental backup, rather than a full one. It is passed to the xtrabackup child process. When this option is specified, either --incremental-lsn or --incremental-basedir can also be given. If neither option is given, option --incremental-basedir is passed to xtrabackup by default, set to the first timestamped backup directory in the backup base directory.
4936+
4937+=item --incremental-basedir=DIRECTORY
4938+
4939+This option specifies the directory containing the full backup that is the base dataset for the incremental backup. The option accepts a string argument. It is used with the --incremental option.
4940+
4941+=item --incremental-dir=DIRECTORY
4942+
4943+This option specifies the directory where the incremental backup will be combined with the full backup to make a new full backup. The option accepts a string argument. It is used with the --incremental option.
4944+
4945+=item --incremental-lsn
4946+
4947+This option specifies the log sequence number (LSN) to use for the incremental backup. The option accepts a string argument. It is used with the --incremental option. It is used instead of specifying --incremental-basedir. For databases created by MySQL and Percona Server 5.0-series versions, specify the LSN as two 32-bit integers in high:low format. For databases created in 5.1 and later, specify the LSN as a single 64-bit integer.
4948+
4949+=item --no-lock
4950+
4951+Use this option to disable table lock with "FLUSH TABLES WITH READ LOCK". Use it only if ALL your tables are InnoDB and you DO NOT CARE about the binary log position of the backup.
4952+
4953+=item --no-timestamp
4954+
4955+This option prevents creation of a time-stamped subdirectory of the BACKUP-ROOT-DIR given on the command line. When it is specified, the backup is done in BACKUP-ROOT-DIR instead.
4956+
4957+=item --parallel=NUMBER-OF-THREADS
4958+
4959+This option specifies the number of threads the xtrabackup child process should use to back up files concurrently. The option accepts an integer argument. It is passed directly to xtrabackup's --parallel option. See the xtrabackup documentation for details.
4960+
4961+
4962+=item --password=WORD
4963+
4964+This option specifies the password to use when connecting to the database. It accepts a string argument. It is passed to the mysql child process without alteration. See mysql --help for details.
4965+
4966+=item --port=PORT
4967+
4968+This option specifies the port to use when connecting to the database server with TCP/IP. The option accepts a string argument. It is passed to the mysql child process. It is passed to the mysql child process without alteration. See mysql --help for details.
4969+
4970+=item --redo-only
4971+
4972+This option is passed directly to xtrabackup's --apply-log-only option. This forces xtrabackup to skip the "rollback" phase and do a "redo" only. This is necessary if the backup will have incremental changes applied to it later. See the xtrabackup documentation for details.
4973+
4974+=item --remote-host=HOSTNAME
4975+
4976+This option specifies the remote host on which the backup files will be created, by using an ssh connection. The option accepts a string argument.
4977+
4978+=item --safe-slave-backup
4979+
4980+Stop slave SQL thread and wait to start backup until Slave_open_temp_tables in "SHOW STATUS" is zero. If there are no open temporary tables, the backup will take place, otherwise the SQL thread will be started and stopped until there are no open temporary tables. The backup will fail if Slave_open_temp_tables does not become zero after --safe-slave-backup-timeout seconds. The slave SQL thread will be restarted when the backup finishes.
4981+
4982+=item --safe-slave-backup-timeout
4983+
4984+How many seconds --safe-slave-backup should wait for Slave_open_temp_tables to become zero. (default 300)
4985+
4986+=item --scpopt=SCP-OPTIONS
4987+
4988+This option specifies the command line options to pass to scp when the option --remost-host is specified. The option accepts a string argument. If the option is not specified, the default options are "-Cp -c arcfour".
4989+
4990+=item --slave-info
4991+
4992+This option is useful when backing up a replication slave server. It prints the binary log position and name of the master server. It also writes this information to the "xtrabackup_slave_info" file as a "CHANGE MASTER" command. A new slave for this master can be set up by starting a slave server on this backup and issuing a "CHANGE MASTER" command with the binary log position saved in the "xtrabackup_slave_info" file.
4993+
4994+=item --socket=SOCKET
4995+
4996+This option specifies the socket to use when connecting to the local database server with a UNIX domain socket. The option accepts a string argument. It is passed to the mysql child process without alteration. See mysql --help for details.
4997+
4998+=item --stream=[tar|. . .]
4999+
5000+This option specifies the format in which to do the streamed backup. The option accepts a string argument. The backup will be done to STDOUT in the specified format. Currently, the only supported format is tar. Uses tar4ibd, which is available in XtraBackup distributions.
The diff has been truncated for viewing.