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