Merge lp:~akopytov/percona-xtrabackup/bug1079700-2.0 into lp:percona-xtrabackup/2.0
- bug1079700-2.0
- Merge into 2.0
Status: | Merged |
---|---|
Approved by: | Laurynas Biveinis |
Approved revision: | 556 |
Merged at revision: | 560 |
Proposed branch: | lp:~akopytov/percona-xtrabackup/bug1079700-2.0 |
Merge into: | lp:percona-xtrabackup/2.0 |
Diff against target: |
2342 lines (+854/-211) 11 files modified
patches/innodb51.patch (+116/-22) patches/innodb51_builtin.patch (+123/-21) patches/innodb55.patch (+118/-22) patches/innodb56.patch (+102/-26) patches/xtradb51.patch (+118/-25) patches/xtradb55.patch (+106/-23) src/xtrabackup.cc (+105/-39) test/inc/common.sh (+19/-0) test/t/ddl.sh (+37/-31) test/testrun.sh (+3/-1) utils/build.sh (+7/-1) |
To merge this branch: | bzr merge lp:~akopytov/percona-xtrabackup/bug1079700-2.0 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
Bug #1079700: Issues with renaming/rotating tables during the backup
stage
The problem was in the way XtraBackup handled DDL on individual
tablespaces on the backup stage. It first created a list of tablespaces
to copy which is represented by fil_system, but when starting the actual
tablespace copy operation later, it opened tablespace files by name. If
a tablespace file could not be opened, XtraBackup assumed the tablespace
got removed after the fil_system list was created and ignored the
tablespaces. This naturally only worked for cases when the tablespace
got dropped. A renamed tablespace would be missing in the resulting
backup, and tablespace rotations resulted in a missing tablespace and a
duplicate copy of another tablespace participating in rotation.
The idea of the fix is to make sure that once a tablespace is added to
fil_system, the underlying file is copied to backup with the same name
and space ID, regardless of what operations have been performed on the
tablespace/file during the backup procedure.
The only way to achieve that is to reuse file handles created when
opening tablespaces and adding them to fil_system, i.e. never attempt to
access tablespaces by name and rely on the fact the an open file handle
will always point to the same inode, even if the file is unlink()ed or
rename()d along the way. In other words, exclude the case when we are
going to copy a tablespace, but the file does not exist already.
This requires changes to fil_load_
the file handle after adding a space/node to fil_system, but keep the
node open and assign the handle to node->handle. We could use
fil_node_
and open the tablespace file by name, which would still leave some room
for a race condition during the time when fil_system is populated. This
also requires XtraBackup to close the node correctly basically to comply
with various invariants enforced by fil_validate() in debug builds. This
part is implemented in XtraBackup in xb_fil_
We also want to reuse file handles in fil_load_
only at the backup stage. Historically, XtraBackup patches used
recv_recovery_on to detect whether we are currently in the 'backup' or
'recovery' mode. That doesn't always work reliably. For example, we may
initialize fil_system before we start recovery to apply an incremental
backup. So recovery is still not started, but we are not in the backup
mode either. To circumvent that, the patch introduces another global
variable srv_backup_mode which is set by XtraBackup only in
xtrabackup_
support in innodb56.patch to use srv_backup_mode instead of
recv_recovery_on.
Another change necessitated by the patch is ignoring deleted tablespaces
on recovery, which has been implemented in XB patches to
recv_apply_
recovery and the underlying file is deleted, possible updates to the
same tablespace done before deleting the tablespace are left in the redo
log. They will be ignored by the recovery code. This can never cause any
problems for server, because file creation/removal is done immediately,
so on recovery InnoDB detects missing tablespace files and does not the
corresponding log records to the hash table (see the first lines in
recv_add_
underlying file will be present when recovery starts, but then get
deleted when MLOG_FILE_DELETE is replayed, i.e. after all log records
from the current batch have been added to the hash table. As a result,
log records corresponding to the deleted tablespace are ignore, but are
still left in the hash table, so recv_apply_
forever waiting for recv_sys->n_addrs to become zero. This was also
possible with XtraBackup before this fix, i.e. when a tablespace is
removed after it has been copied by XtraBackup. This fix just makes this
condition more likely to occur, as we always copy all tablespaces rather
than ignore those removed before the copy operation is tarted.
To fix the above case, we also check for deleted tablespaces in
recv_apply_
tablespaces are marked as processed and recv_sys->n_addrs is decremented
accordingly to not leave spurious unprocessed log records in the hash
table.
Finally, now that we reuse fil_system file handles again, bug #870119
needs another fix. I.e. the number of open file handles grows to the
number of tablespaces we want to copy, so we want to prevent InnoDB LRU
policies from kicking in and closing/reusing file handles. There are
multiple ways to achieve that. Patching InnoDB code to disable
fil_system LRU and file closing policies in InnoDB appeared to be too
risky. The easiest one is to set the allowed number of open InnoDB files
to some vary large value unconditionally (i.e. override
innodb_open_files with the maximum possible value, LONG_MAX). InnoDB
does not allocate any resource for each srv_max_
increment. It's just the maximum possible LRU list length, so this
change does not incur any additional resource consumption.
This revision also extends bug722638.sh (since there's 95% overlap
between that one and the test case for this bug), and renames
bug722638.sh to ddl.sh to better reflect the contents. It also backports
record_db_state() / verify_db_state() from the 2.1 test suite, because
messing with individual table checksums and checksum_table looks rather
cumbersome with a higher number of tables in the test.
http://

Laurynas Biveinis (laurynas-biveinis) wrote : | # |

Alexey Kopytov (akopytov) wrote : | # |
Hi Laurynas,
On Wed, 08 May 2013 14:48:26 -0000, Laurynas Biveinis wrote:
> Review: Needs Information
>
> - The MLOG_FILE_DELETE bits need reconcilation and/or explanation
> on why the already existing hashed log rec handling in the
> patches for buf_page_read_low() is not enough. Maybe it's
> possible to tweak buf_page_read_low() patch instead of adding
> more patches to log0recv.c? Please see
> http://
> https:/
> which I have closed as Invalid due to this MP.
>
The explanation is that you did not port the patch for bug #43948 to
innodb56.patch. Now that I have patched recv_apply_
the fix for bug 43948 in PS and innodb51.
But since the goal is to get rid of all those patches, they will be
"reconciled" naturally.
> - Will the following work:
> - XtraBackup creates a list of tablespaces;
> - CREATE TABLE foo is issued (optionally maybe even CREATE
> DATABASE first);
> - XtraBackup proceeds with backup;
> - Incremental backup is taken. Will it contain foo? It is
> possible that some of the foo writes will be captured in the
> full backup redo log backup.
> I guess this question boils down to "is fil_system snapshot
> taking atomic with the rest of backup state." CREATE TABLE
> specifically because other scenarios seem to be covered by this
> fix. I am not implying that I suspect it will or will not, I
> don't know and am curious.
>
fil_op_
MLOG_FILE_CREATE and the tablespace already exists. So if the tablespace
makes it into fil_system at the backup stage, XtraBackup will ignore
MLOG_FILE_CREATE. Otherwise it will replay it. Not sure what difference
a subsequent incremental backup would make.
> - This might be outside the scope of the current fix, but since
> you are backporting the mysqldump backup verifier, I am
> mentioning it here. If there's a bug/blueprint open for this,
> please point me there: mysqldump verification probably would miss
> secondary index tree corruptions, wouldn't it?
>
Both mysqldump and CHECKSUM TABLE verification are identical for InnoDB.
CHECKSUM TABLE basically does "SELECT * FROM table" internally and
calculates checksums for all values in all rows. So corruption in
secondary index pages will also go unnoticed.
> - What are the s/AM_CONFIG_
> Some bug fixed? If yes, is there a # ref?
>
It is a backport of the fix for bug #1164958 to older PS/MySQL 5.1 versions.
> - Likewise for configure.cmake patch bits?
>
Likewise, backports of the fix for
http://
> - I recall seeing utils/build.sh patch elsewhere, yet there is
> only one unmerged revision in this MP. Is this intended?
>
That was for 2.1.

Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Hi Alexey -
> > - The MLOG_FILE_DELETE bits need reconcilation and/or explanation
> > http://
>
> The explanation is that you did not port the patch for bug #43948 to
> innodb56.patch. Now that I have patched recv_apply_
> the fix for bug 43948 in PS and innodb51.
Yes, I was wondering about other than innodb56.patch patches. The fact that I didn't patch innodb56.patch is/was https:/
> > - This might be outside the scope of the current fix, but since
> > you are backporting the mysqldump backup verifier, I am
> > mentioning it here. If there's a bug/blueprint open for this,
> > please point me there: mysqldump verification probably would miss
> > secondary index tree corruptions, wouldn't it?
> >
>
> Both mysqldump and CHECKSUM TABLE verification are identical for InnoDB.
> CHECKSUM TABLE basically does "SELECT * FROM table" internally and
> calculates checksums for all values in all rows. So corruption in
> secondary index pages will also go unnoticed.
I didn't mention CHECKSUM TABLE anywhere in my comment for this very reason. So do we want to do something re. secondary index tree verifications?
Preview Diff
1 | === modified file 'patches/innodb51.patch' |
2 | --- patches/innodb51.patch 2013-04-16 14:29:50 +0000 |
3 | +++ patches/innodb51.patch 2013-05-08 05:16:27 +0000 |
4 | @@ -444,7 +444,60 @@ |
5 | if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { |
6 | fprintf(stderr, |
7 | "InnoDB: Error: the size of single-table tablespace" |
8 | -@@ -3425,7 +3530,7 @@ |
9 | +@@ -3414,7 +3519,51 @@ |
10 | + |
11 | + fil_node_create(filepath, 0, space_id, FALSE); |
12 | + func_exit: |
13 | +- os_file_close(file); |
14 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
15 | ++ inconsistencies between the file name and the actual tablespace contents |
16 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
17 | ++ the actual copy operation. */ |
18 | ++ if (srv_backup_mode) { |
19 | ++ |
20 | ++ fil_node_t* node; |
21 | ++ fil_space_t* space; |
22 | ++ |
23 | ++ mutex_enter(&fil_system->mutex); |
24 | ++ |
25 | ++ space = fil_space_get_by_id(space_id); |
26 | ++ |
27 | ++ if (space) { |
28 | ++ node = UT_LIST_GET_LAST(space->chain); |
29 | ++ |
30 | ++ /* The handle will be closed by xtrabackup in |
31 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
32 | ++ make sure no one calls fil_node_open_file() |
33 | ++ (i.e. attempts to reopen the tablespace by name) during |
34 | ++ the backup stage. */ |
35 | ++ |
36 | ++ node->open = TRUE; |
37 | ++ node->handle = file; |
38 | ++ |
39 | ++ /* The following is copied from fil_node_open_file() to |
40 | ++ pass fil_system validity checks. We cannot use |
41 | ++ fil_node_open_file() directly, as that would re-open the |
42 | ++ file by name and create another file handle. */ |
43 | ++ |
44 | ++ fil_system->n_open++; |
45 | ++ |
46 | ++ if (space->purpose == FIL_TABLESPACE && |
47 | ++ space->id != 0) { |
48 | ++ |
49 | ++ /* Put the node to the LRU list */ |
50 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
51 | ++ } |
52 | ++ } |
53 | ++ |
54 | ++ mutex_exit(&fil_system->mutex); |
55 | ++ } else { |
56 | ++ |
57 | ++ os_file_close(file); |
58 | ++ } |
59 | + ut_free(buf2); |
60 | + mem_free(filepath); |
61 | + } |
62 | +@@ -3425,7 +3574,7 @@ |
63 | idea is to read as much good data as we can and jump over bad data. |
64 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
65 | of the directory */ |
66 | @@ -453,7 +506,7 @@ |
67 | int |
68 | fil_file_readdir_next_file( |
69 | /*=======================*/ |
70 | -@@ -3469,7 +3574,7 @@ |
71 | +@@ -3469,7 +3618,7 @@ |
72 | @return DB_SUCCESS or error number */ |
73 | UNIV_INTERN |
74 | ulint |
75 | @@ -462,7 +515,7 @@ |
76 | /*===================================*/ |
77 | { |
78 | int ret; |
79 | -@@ -3525,7 +3630,9 @@ |
80 | +@@ -3525,7 +3674,9 @@ |
81 | dbinfo.name); |
82 | srv_normalize_path_for_win(dbpath); |
83 | |
84 | @@ -473,7 +526,7 @@ |
85 | |
86 | if (dbdir != NULL) { |
87 | /* printf("Opened dir %s\n", dbinfo.name); */ |
88 | -@@ -3551,8 +3658,11 @@ |
89 | +@@ -3551,8 +3702,11 @@ |
90 | ".ibd")) { |
91 | /* The name ends in .ibd; try opening |
92 | the file */ |
93 | @@ -486,7 +539,7 @@ |
94 | } |
95 | next_file_item: |
96 | ret = fil_file_readdir_next_file(&err, |
97 | -@@ -3724,15 +3834,97 @@ |
98 | +@@ -3724,15 +3878,97 @@ |
99 | "InnoDB: in InnoDB data dictionary" |
100 | " has tablespace id %lu,\n" |
101 | "InnoDB: but tablespace with that id" |
102 | @@ -592,7 +645,7 @@ |
103 | } else { |
104 | ut_print_timestamp(stderr); |
105 | fputs(" InnoDB: Error: table ", stderr); |
106 | -@@ -4121,7 +4313,7 @@ |
107 | +@@ -4121,7 +4357,7 @@ |
108 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
109 | mutex. */ |
110 | static |
111 | @@ -601,7 +654,7 @@ |
112 | fil_node_prepare_for_io( |
113 | /*====================*/ |
114 | fil_node_t* node, /*!< in: file node */ |
115 | -@@ -4141,10 +4333,13 @@ |
116 | +@@ -4141,10 +4377,13 @@ |
117 | } |
118 | |
119 | if (node->open == FALSE) { |
120 | @@ -616,7 +669,7 @@ |
121 | } |
122 | |
123 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
124 | -@@ -4157,6 +4352,8 @@ |
125 | +@@ -4157,6 +4396,8 @@ |
126 | } |
127 | |
128 | node->n_pending++; |
129 | @@ -625,7 +678,7 @@ |
130 | } |
131 | |
132 | /********************************************************************//** |
133 | -@@ -4292,7 +4489,9 @@ |
134 | +@@ -4292,7 +4533,9 @@ |
135 | ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE) |
136 | || !ibuf_bitmap_page(zip_size, block_offset) |
137 | || sync || is_log); |
138 | @@ -636,7 +689,7 @@ |
139 | || ibuf_page(space_id, zip_size, block_offset, NULL)); |
140 | # endif /* UNIV_LOG_DEBUG */ |
141 | if (sync) { |
142 | -@@ -4341,6 +4540,16 @@ |
143 | +@@ -4341,6 +4584,16 @@ |
144 | |
145 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
146 | |
147 | @@ -710,7 +763,7 @@ |
148 | |
149 | --- a/storage/innodb_plugin/include/srv0srv.h |
150 | +++ b/storage/innodb_plugin/include/srv0srv.h |
151 | -@@ -202,6 +202,10 @@ |
152 | +@@ -202,6 +202,11 @@ |
153 | extern ulong srv_max_purge_lag; |
154 | |
155 | extern ulong srv_replication_delay; |
156 | @@ -718,6 +771,7 @@ |
157 | +extern ibool srv_read_only; |
158 | +extern ibool srv_fake_write; |
159 | +extern ibool srv_apply_log_only; |
160 | ++extern ibool srv_backup_mode; |
161 | /*-------------------------------------------*/ |
162 | |
163 | extern ulint srv_n_rows_inserted; |
164 | @@ -912,7 +966,35 @@ |
165 | || (recv_addr->state == RECV_BEING_PROCESSED) |
166 | || (recv_addr->state == RECV_PROCESSED)) { |
167 | |
168 | -@@ -2297,7 +2298,7 @@ |
169 | +@@ -1762,6 +1763,18 @@ |
170 | + ulint zip_size = fil_space_get_zip_size(space); |
171 | + ulint page_no = recv_addr->page_no; |
172 | + |
173 | ++ /* By now we have replayed all DDL log records from the |
174 | ++ current batch. Check if the space ID is still valid in |
175 | ++ the entry being processed, and ignore it if it is not.*/ |
176 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
177 | ++ |
178 | ++ ut_a(recv_sys->n_addrs); |
179 | ++ |
180 | ++ recv_addr->state = RECV_PROCESSED; |
181 | ++ recv_sys->n_addrs--; |
182 | ++ |
183 | ++ goto next; |
184 | ++ } |
185 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
186 | + if (!has_printed) { |
187 | + ut_print_timestamp(stderr); |
188 | +@@ -1795,7 +1808,7 @@ |
189 | + |
190 | + mutex_enter(&(recv_sys->mutex)); |
191 | + } |
192 | +- |
193 | ++next: |
194 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
195 | + } |
196 | + |
197 | +@@ -2297,7 +2310,7 @@ |
198 | || type == MLOG_FILE_RENAME |
199 | || type == MLOG_FILE_DELETE) { |
200 | ut_a(space); |
201 | @@ -921,7 +1003,7 @@ |
202 | if (recv_replay_file_ops) { |
203 | |
204 | /* In ibbackup --apply-log, replay an .ibd file |
205 | -@@ -2320,7 +2321,7 @@ |
206 | +@@ -2320,7 +2333,7 @@ |
207 | ut_error; |
208 | } |
209 | } |
210 | @@ -930,7 +1012,7 @@ |
211 | /* In normal mysqld crash recovery we do not try to |
212 | replay file operations */ |
213 | #ifdef UNIV_LOG_LSN_DEBUG |
214 | -@@ -2737,8 +2738,11 @@ |
215 | +@@ -2737,8 +2750,11 @@ |
216 | |
217 | fprintf(stderr, |
218 | "InnoDB: Doing recovery: scanned up to" |
219 | @@ -944,7 +1026,7 @@ |
220 | } |
221 | } |
222 | |
223 | -@@ -2841,7 +2845,7 @@ |
224 | +@@ -2841,7 +2857,7 @@ |
225 | "InnoDB: Reading tablespace information" |
226 | " from the .ibd files...\n"); |
227 | |
228 | @@ -953,7 +1035,7 @@ |
229 | |
230 | /* If we are using the doublewrite method, we will |
231 | check if there are half-written pages in data files, |
232 | -@@ -2850,12 +2854,14 @@ |
233 | +@@ -2850,12 +2866,14 @@ |
234 | |
235 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
236 | |
237 | @@ -969,7 +1051,7 @@ |
238 | } |
239 | } |
240 | |
241 | -@@ -3005,6 +3011,7 @@ |
242 | +@@ -3005,6 +3023,7 @@ |
243 | recv_sys->recovered_lsn = checkpoint_lsn; |
244 | |
245 | srv_start_lsn = checkpoint_lsn; |
246 | @@ -977,7 +1059,7 @@ |
247 | } |
248 | |
249 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
250 | -@@ -3286,6 +3293,7 @@ |
251 | +@@ -3286,6 +3305,7 @@ |
252 | that the data dictionary tables will be free of any locks. |
253 | The data dictionary latch should guarantee that there is at |
254 | most one data dictionary transaction active at a time. */ |
255 | @@ -1102,17 +1184,18 @@ |
256 | secondary index entries for merge sort */ |
257 | --- a/storage/innodb_plugin/srv/srv0srv.c |
258 | +++ b/storage/innodb_plugin/srv/srv0srv.c |
259 | -@@ -374,6 +374,9 @@ |
260 | +@@ -374,6 +374,10 @@ |
261 | |
262 | UNIV_INTERN ulong srv_replication_delay = 0; |
263 | |
264 | +UNIV_INTERN ibool srv_read_only = FALSE; |
265 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
266 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
267 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
268 | /*-------------------------------------------*/ |
269 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
270 | UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; |
271 | -@@ -1002,7 +1005,7 @@ |
272 | +@@ -1002,7 +1006,7 @@ |
273 | } |
274 | |
275 | /* Initialize some INFORMATION SCHEMA internal structures */ |
276 | @@ -1121,7 +1204,7 @@ |
277 | } |
278 | |
279 | /*********************************************************************//** |
280 | -@@ -1013,6 +1016,7 @@ |
281 | +@@ -1013,6 +1017,7 @@ |
282 | /*==========*/ |
283 | { |
284 | os_fast_mutex_free(&srv_conc_mutex); |
285 | @@ -1129,7 +1212,7 @@ |
286 | mem_free(srv_conc_slots); |
287 | srv_conc_slots = NULL; |
288 | |
289 | -@@ -1026,6 +1030,7 @@ |
290 | +@@ -1026,6 +1031,7 @@ |
291 | srv_mysql_table = NULL; |
292 | |
293 | trx_i_s_cache_free(trx_i_s_cache); |
294 | @@ -1347,3 +1430,14 @@ |
295 | |
296 | UNIV_MEM_FREE(buf, n); |
297 | } |
298 | +--- a/configure.in |
299 | ++++ b/configure.in |
300 | +@@ -22,7 +22,7 @@ |
301 | + AM_INIT_AUTOMAKE([1.9 tar-ustar]) |
302 | + AC_PROG_LIBTOOL |
303 | + |
304 | +-AM_CONFIG_HEADER([include/config.h]) |
305 | ++AC_CONFIG_HEADERS([include/config.h]) |
306 | + |
307 | + # Request support for automake silent-rules if available. |
308 | + # Default to verbose output. One can use the configure-time |
309 | |
310 | === modified file 'patches/innodb51_builtin.patch' |
311 | --- patches/innodb51_builtin.patch 2013-04-16 14:29:50 +0000 |
312 | +++ patches/innodb51_builtin.patch 2013-05-08 05:16:27 +0000 |
313 | @@ -231,6 +231,15 @@ |
314 | } |
315 | |
316 | /************************************************************************** |
317 | +@@ -1227,7 +1247,7 @@ |
318 | + return(TRUE); |
319 | + } |
320 | + |
321 | +-#ifdef UNIV_HOTBACKUP |
322 | ++#if 1 |
323 | + /*********************************************************************** |
324 | + Returns the tablespace object for a given id, or NULL if not found from the |
325 | + tablespace memory cache. */ |
326 | @@ -1288,7 +1308,12 @@ |
327 | the file yet; the following calls will open it and update the |
328 | size fields */ |
329 | @@ -410,7 +419,60 @@ |
330 | if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { |
331 | fprintf(stderr, |
332 | "InnoDB: Error: the size of single-table tablespace" |
333 | -@@ -3152,7 +3256,7 @@ |
334 | +@@ -3143,7 +3247,51 @@ |
335 | + |
336 | + fil_node_create(filepath, 0, space_id, FALSE); |
337 | + func_exit: |
338 | +- os_file_close(file); |
339 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
340 | ++ inconsistencies between the file name and the actual tablespace contents |
341 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
342 | ++ the actual copy operation. */ |
343 | ++ if (srv_backup_mode) { |
344 | ++ |
345 | ++ fil_node_t* node; |
346 | ++ fil_space_t* space; |
347 | ++ |
348 | ++ mutex_enter(&fil_system->mutex); |
349 | ++ |
350 | ++ space = fil_get_space_for_id_low(space_id); |
351 | ++ |
352 | ++ if (space) { |
353 | ++ node = UT_LIST_GET_LAST(space->chain); |
354 | ++ |
355 | ++ /* The handle will be closed by xtrabackup in |
356 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
357 | ++ make sure no one calls fil_node_open_file() |
358 | ++ (i.e. attempts to reopen the tablespace by name) during |
359 | ++ the backup stage. */ |
360 | ++ |
361 | ++ node->open = TRUE; |
362 | ++ node->handle = file; |
363 | ++ |
364 | ++ /* The following is copied from fil_node_open_file() to |
365 | ++ pass fil_system validity checks. We cannot use |
366 | ++ fil_node_open_file() directly, as that would re-open the |
367 | ++ file by name and create another file handle. */ |
368 | ++ |
369 | ++ fil_system->n_open++; |
370 | ++ |
371 | ++ if (space->purpose == FIL_TABLESPACE && |
372 | ++ space->id != 0) { |
373 | ++ |
374 | ++ /* Put the node to the LRU list */ |
375 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
376 | ++ } |
377 | ++ } |
378 | ++ |
379 | ++ mutex_exit(&fil_system->mutex); |
380 | ++ } else { |
381 | ++ |
382 | ++ os_file_close(file); |
383 | ++ } |
384 | + ut_free(buf2); |
385 | + mem_free(filepath); |
386 | + } |
387 | +@@ -3152,7 +3300,7 @@ |
388 | A fault-tolerant function that tries to read the next file name in the |
389 | directory. We retry 100 times if os_file_readdir_next_file() returns -1. The |
390 | idea is to read as much good data as we can and jump over bad data. */ |
391 | @@ -419,7 +481,7 @@ |
392 | int |
393 | fil_file_readdir_next_file( |
394 | /*=======================*/ |
395 | -@@ -3197,7 +3301,7 @@ |
396 | +@@ -3197,7 +3345,7 @@ |
397 | space id is != 0. */ |
398 | |
399 | ulint |
400 | @@ -428,7 +490,7 @@ |
401 | /*===================================*/ |
402 | /* out: DB_SUCCESS or error number */ |
403 | { |
404 | -@@ -3254,7 +3358,9 @@ |
405 | +@@ -3254,7 +3402,9 @@ |
406 | dbinfo.name); |
407 | srv_normalize_path_for_win(dbpath); |
408 | |
409 | @@ -439,7 +501,7 @@ |
410 | |
411 | if (dbdir != NULL) { |
412 | /* printf("Opened dir %s\n", dbinfo.name); */ |
413 | -@@ -3280,8 +3386,11 @@ |
414 | +@@ -3280,8 +3430,11 @@ |
415 | ".ibd")) { |
416 | /* The name ends in .ibd; try opening |
417 | the file */ |
418 | @@ -452,7 +514,7 @@ |
419 | } |
420 | next_file_item: |
421 | ret = fil_file_readdir_next_file(&err, |
422 | -@@ -3500,15 +3609,100 @@ |
423 | +@@ -3500,15 +3653,100 @@ |
424 | "InnoDB: in InnoDB data dictionary" |
425 | " has tablespace id %lu,\n" |
426 | "InnoDB: but tablespace with that id" |
427 | @@ -561,7 +623,7 @@ |
428 | } else { |
429 | ut_print_timestamp(stderr); |
430 | fputs(" InnoDB: Error: table ", stderr); |
431 | -@@ -3901,7 +4095,7 @@ |
432 | +@@ -3901,7 +4139,7 @@ |
433 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
434 | mutex. */ |
435 | static |
436 | @@ -570,7 +632,7 @@ |
437 | fil_node_prepare_for_io( |
438 | /*====================*/ |
439 | fil_node_t* node, /* in: file node */ |
440 | -@@ -3921,10 +4115,14 @@ |
441 | +@@ -3921,10 +4159,14 @@ |
442 | } |
443 | |
444 | if (node->open == FALSE) { |
445 | @@ -586,7 +648,7 @@ |
446 | } |
447 | |
448 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
449 | -@@ -3937,6 +4135,8 @@ |
450 | +@@ -3937,6 +4179,8 @@ |
451 | } |
452 | |
453 | node->n_pending++; |
454 | @@ -595,7 +657,7 @@ |
455 | } |
456 | |
457 | /************************************************************************ |
458 | -@@ -4067,7 +4267,9 @@ |
459 | +@@ -4067,7 +4311,9 @@ |
460 | ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE) |
461 | || !ibuf_bitmap_page(block_offset) || sync || is_log); |
462 | #ifdef UNIV_SYNC_DEBUG |
463 | @@ -606,7 +668,7 @@ |
464 | || ibuf_page(space_id, block_offset)); |
465 | #endif |
466 | #endif |
467 | -@@ -4112,6 +4314,16 @@ |
468 | +@@ -4112,6 +4358,16 @@ |
469 | |
470 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
471 | |
472 | @@ -746,7 +808,7 @@ |
473 | extern ulint srv_pool_size; |
474 | extern ulint srv_awe_window_size; |
475 | extern ulint srv_mem_pool_size; |
476 | -@@ -138,6 +141,10 @@ |
477 | +@@ -138,6 +141,11 @@ |
478 | extern ulong srv_max_purge_lag; |
479 | extern ibool srv_use_awe; |
480 | extern ibool srv_use_adaptive_hash_indexes; |
481 | @@ -754,6 +816,7 @@ |
482 | +extern ibool srv_read_only; |
483 | +extern ibool srv_fake_write; |
484 | +extern ibool srv_apply_log_only; |
485 | ++extern ibool srv_backup_mode; |
486 | /*-------------------------------------------*/ |
487 | |
488 | extern ulint srv_n_rows_inserted; |
489 | @@ -956,7 +1019,34 @@ |
490 | || (recv_addr->state == RECV_BEING_PROCESSED) |
491 | || (recv_addr->state == RECV_PROCESSED)) { |
492 | |
493 | -@@ -1926,7 +1927,7 @@ |
494 | +@@ -1429,6 +1430,18 @@ |
495 | + space = recv_addr->space; |
496 | + page_no = recv_addr->page_no; |
497 | + |
498 | ++ /* By now we have replayed all DDL log records from the |
499 | ++ current batch. Check if the space ID is still valid in |
500 | ++ the entry being processed, and ignore it if it is not.*/ |
501 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
502 | ++ |
503 | ++ ut_a(recv_sys->n_addrs); |
504 | ++ |
505 | ++ recv_addr->state = RECV_PROCESSED; |
506 | ++ recv_sys->n_addrs--; |
507 | ++ |
508 | ++ goto next; |
509 | ++ } |
510 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
511 | + if (!has_printed) { |
512 | + ut_print_timestamp(stderr); |
513 | +@@ -1463,6 +1476,7 @@ |
514 | + mutex_enter(&(recv_sys->mutex)); |
515 | + } |
516 | + |
517 | ++next: |
518 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
519 | + } |
520 | + |
521 | +@@ -1926,7 +1940,7 @@ |
522 | } else if (store_to_hash && (type == MLOG_FILE_CREATE |
523 | || type == MLOG_FILE_RENAME |
524 | || type == MLOG_FILE_DELETE)) { |
525 | @@ -965,7 +1055,7 @@ |
526 | if (recv_replay_file_ops) { |
527 | |
528 | /* In ibbackup --apply-log, replay an .ibd file |
529 | -@@ -1949,7 +1950,7 @@ |
530 | +@@ -1949,7 +1963,7 @@ |
531 | ut_a(0); |
532 | } |
533 | } |
534 | @@ -974,7 +1064,7 @@ |
535 | /* In normal mysqld crash recovery we do not try to |
536 | replay file operations */ |
537 | } else if (store_to_hash) { |
538 | -@@ -2360,9 +2361,12 @@ |
539 | +@@ -2360,9 +2374,12 @@ |
540 | |
541 | fprintf(stderr, |
542 | "InnoDB: Doing recovery: scanned up to" |
543 | @@ -989,7 +1079,7 @@ |
544 | } |
545 | } |
546 | |
547 | -@@ -2462,7 +2466,7 @@ |
548 | +@@ -2462,7 +2479,7 @@ |
549 | "InnoDB: Reading tablespace information" |
550 | " from the .ibd files...\n"); |
551 | |
552 | @@ -998,7 +1088,7 @@ |
553 | |
554 | /* If we are using the doublewrite method, we will |
555 | check if there are half-written pages in data files, |
556 | -@@ -2471,12 +2475,14 @@ |
557 | +@@ -2471,12 +2488,14 @@ |
558 | |
559 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
560 | |
561 | @@ -1014,7 +1104,7 @@ |
562 | } |
563 | } |
564 | |
565 | -@@ -2611,6 +2617,7 @@ |
566 | +@@ -2611,6 +2630,7 @@ |
567 | recv_sys->recovered_lsn = checkpoint_lsn; |
568 | |
569 | srv_start_lsn = checkpoint_lsn; |
570 | @@ -1022,7 +1112,7 @@ |
571 | } |
572 | |
573 | contiguous_lsn = ut_dulint_align_down(recv_sys->scanned_lsn, |
574 | -@@ -2910,6 +2917,7 @@ |
575 | +@@ -2910,6 +2930,7 @@ |
576 | /* Switch latching order checks on in sync0sync.c */ |
577 | sync_order_checks_on = TRUE; |
578 | #endif |
579 | @@ -1030,7 +1120,7 @@ |
580 | if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { |
581 | /* Rollback the uncommitted transactions which have no user |
582 | session */ |
583 | -@@ -2917,6 +2925,7 @@ |
584 | +@@ -2917,6 +2938,7 @@ |
585 | os_thread_create(trx_rollback_or_clean_all_without_sess, |
586 | (void *)&i, NULL); |
587 | } |
588 | @@ -1346,17 +1436,18 @@ |
589 | ulint srv_pool_size = ULINT_MAX; /* size in pages; MySQL inits |
590 | this to size in kilobytes but |
591 | we normalize this to pages in |
592 | -@@ -363,6 +367,9 @@ |
593 | +@@ -363,6 +367,10 @@ |
594 | ibool srv_use_awe = FALSE; |
595 | ibool srv_use_adaptive_hash_indexes = TRUE; |
596 | |
597 | +ibool srv_read_only = FALSE; |
598 | +ibool srv_fake_write = FALSE; |
599 | +ibool srv_apply_log_only = FALSE; |
600 | ++ibool srv_backup_mode = FALSE; |
601 | /*-------------------------------------------*/ |
602 | ulong srv_n_spin_wait_rounds = 20; |
603 | ulong srv_n_free_tickets_to_enter = 500; |
604 | -@@ -985,6 +992,7 @@ |
605 | +@@ -985,6 +993,7 @@ |
606 | srv_general_init(void) |
607 | /*==================*/ |
608 | { |
609 | @@ -1605,3 +1696,14 @@ |
610 | |
611 | if (rec_len != UNIV_SQL_NULL) { |
612 | n_not_null[i]++; |
613 | +--- a/configure.in |
614 | ++++ b/configure.in |
615 | +@@ -22,7 +22,7 @@ |
616 | + AM_INIT_AUTOMAKE([1.9 tar-ustar]) |
617 | + AC_PROG_LIBTOOL |
618 | + |
619 | +-AM_CONFIG_HEADER([include/config.h]) |
620 | ++AC_CONFIG_HEADERS([include/config.h]) |
621 | + |
622 | + # Request support for automake silent-rules if available. |
623 | + # Default to verbose output. One can use the configure-time |
624 | |
625 | === modified file 'patches/innodb55.patch' |
626 | --- patches/innodb55.patch 2013-04-16 14:29:50 +0000 |
627 | +++ patches/innodb55.patch 2013-05-08 05:16:27 +0000 |
628 | @@ -433,7 +433,60 @@ |
629 | if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { |
630 | fprintf(stderr, |
631 | "InnoDB: Error: the size of single-table tablespace" |
632 | -@@ -3476,7 +3581,7 @@ |
633 | +@@ -3465,7 +3570,51 @@ |
634 | + |
635 | + fil_node_create(filepath, 0, space_id, FALSE); |
636 | + func_exit: |
637 | +- os_file_close(file); |
638 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
639 | ++ inconsistencies between the file name and the actual tablespace contents |
640 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
641 | ++ the actual copy operation. */ |
642 | ++ if (srv_backup_mode) { |
643 | ++ |
644 | ++ fil_node_t* node; |
645 | ++ fil_space_t* space; |
646 | ++ |
647 | ++ mutex_enter(&fil_system->mutex); |
648 | ++ |
649 | ++ space = fil_space_get_by_id(space_id); |
650 | ++ |
651 | ++ if (space) { |
652 | ++ node = UT_LIST_GET_LAST(space->chain); |
653 | ++ |
654 | ++ /* The handle will be closed by xtrabackup in |
655 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
656 | ++ make sure no one calls fil_node_open_file() |
657 | ++ (i.e. attempts to reopen the tablespace by name) during |
658 | ++ the backup stage. */ |
659 | ++ |
660 | ++ node->open = TRUE; |
661 | ++ node->handle = file; |
662 | ++ |
663 | ++ /* The following is copied from fil_node_open_file() to |
664 | ++ pass fil_system validity checks. We cannot use |
665 | ++ fil_node_open_file() directly, as that would re-open the |
666 | ++ file by name and create another file handle. */ |
667 | ++ |
668 | ++ fil_system->n_open++; |
669 | ++ |
670 | ++ if (space->purpose == FIL_TABLESPACE && |
671 | ++ space->id != 0) { |
672 | ++ |
673 | ++ /* Put the node to the LRU list */ |
674 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
675 | ++ } |
676 | ++ } |
677 | ++ |
678 | ++ mutex_exit(&fil_system->mutex); |
679 | ++ } else { |
680 | ++ |
681 | ++ os_file_close(file); |
682 | ++ } |
683 | + ut_free(buf2); |
684 | + mem_free(filepath); |
685 | + } |
686 | +@@ -3476,7 +3625,7 @@ |
687 | idea is to read as much good data as we can and jump over bad data. |
688 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
689 | of the directory */ |
690 | @@ -442,7 +495,7 @@ |
691 | int |
692 | fil_file_readdir_next_file( |
693 | /*=======================*/ |
694 | -@@ -3520,7 +3625,7 @@ |
695 | +@@ -3520,7 +3669,7 @@ |
696 | @return DB_SUCCESS or error number */ |
697 | UNIV_INTERN |
698 | ulint |
699 | @@ -451,7 +504,7 @@ |
700 | /*===================================*/ |
701 | { |
702 | int ret; |
703 | -@@ -3576,7 +3681,9 @@ |
704 | +@@ -3576,7 +3725,9 @@ |
705 | dbinfo.name); |
706 | srv_normalize_path_for_win(dbpath); |
707 | |
708 | @@ -462,7 +515,7 @@ |
709 | |
710 | if (dbdir != NULL) { |
711 | /* printf("Opened dir %s\n", dbinfo.name); */ |
712 | -@@ -3602,8 +3709,11 @@ |
713 | +@@ -3602,8 +3753,11 @@ |
714 | ".ibd")) { |
715 | /* The name ends in .ibd; try opening |
716 | the file */ |
717 | @@ -475,7 +528,7 @@ |
718 | } |
719 | next_file_item: |
720 | ret = fil_file_readdir_next_file(&err, |
721 | -@@ -3775,15 +3885,97 @@ |
722 | +@@ -3775,15 +3929,97 @@ |
723 | "InnoDB: in InnoDB data dictionary" |
724 | " has tablespace id %lu,\n" |
725 | "InnoDB: but tablespace with that id" |
726 | @@ -581,7 +634,7 @@ |
727 | } else { |
728 | ut_print_timestamp(stderr); |
729 | fputs(" InnoDB: Error: table ", stderr); |
730 | -@@ -4172,7 +4364,7 @@ |
731 | +@@ -4172,7 +4408,7 @@ |
732 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
733 | mutex. */ |
734 | static |
735 | @@ -590,7 +643,7 @@ |
736 | fil_node_prepare_for_io( |
737 | /*====================*/ |
738 | fil_node_t* node, /*!< in: file node */ |
739 | -@@ -4192,10 +4384,13 @@ |
740 | +@@ -4192,10 +4428,13 @@ |
741 | } |
742 | |
743 | if (node->open == FALSE) { |
744 | @@ -605,7 +658,7 @@ |
745 | } |
746 | |
747 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
748 | -@@ -4208,6 +4403,8 @@ |
749 | +@@ -4208,6 +4447,8 @@ |
750 | } |
751 | |
752 | node->n_pending++; |
753 | @@ -614,7 +667,7 @@ |
754 | } |
755 | |
756 | /********************************************************************//** |
757 | -@@ -4390,6 +4587,16 @@ |
758 | +@@ -4390,6 +4631,16 @@ |
759 | |
760 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
761 | |
762 | @@ -666,7 +719,7 @@ |
763 | Returns TRUE if a single-table tablespace does not exist in the memory cache, |
764 | --- a/storage/innobase/include/srv0srv.h |
765 | +++ b/storage/innobase/include/srv0srv.h |
766 | -@@ -218,6 +218,10 @@ |
767 | +@@ -218,6 +218,11 @@ |
768 | extern ulong srv_max_purge_lag; |
769 | |
770 | extern ulong srv_replication_delay; |
771 | @@ -674,6 +727,7 @@ |
772 | +extern ibool srv_read_only; |
773 | +extern ibool srv_fake_write; |
774 | +extern ibool srv_apply_log_only; |
775 | ++extern ibool srv_backup_mode; |
776 | /*-------------------------------------------*/ |
777 | |
778 | extern ulint srv_n_rows_inserted; |
779 | @@ -824,7 +878,35 @@ |
780 | || (recv_addr->state == RECV_BEING_PROCESSED) |
781 | || (recv_addr->state == RECV_PROCESSED)) { |
782 | |
783 | -@@ -2308,7 +2309,7 @@ |
784 | +@@ -1774,6 +1775,18 @@ |
785 | + ulint zip_size = fil_space_get_zip_size(space); |
786 | + ulint page_no = recv_addr->page_no; |
787 | + |
788 | ++ /* By now we have replayed all DDL log records from the |
789 | ++ current batch. Check if the space ID is still valid in |
790 | ++ the entry being processed, and ignore it if it is not.*/ |
791 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
792 | ++ |
793 | ++ ut_a(recv_sys->n_addrs); |
794 | ++ |
795 | ++ recv_addr->state = RECV_PROCESSED; |
796 | ++ recv_sys->n_addrs--; |
797 | ++ |
798 | ++ goto next; |
799 | ++ } |
800 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
801 | + if (!has_printed) { |
802 | + ut_print_timestamp(stderr); |
803 | +@@ -1807,7 +1820,7 @@ |
804 | + |
805 | + mutex_enter(&(recv_sys->mutex)); |
806 | + } |
807 | +- |
808 | ++next: |
809 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
810 | + } |
811 | + |
812 | +@@ -2308,7 +2321,7 @@ |
813 | || type == MLOG_FILE_RENAME |
814 | || type == MLOG_FILE_DELETE) { |
815 | ut_a(space); |
816 | @@ -833,7 +915,7 @@ |
817 | if (recv_replay_file_ops) { |
818 | |
819 | /* In ibbackup --apply-log, replay an .ibd file |
820 | -@@ -2331,7 +2332,7 @@ |
821 | +@@ -2331,7 +2344,7 @@ |
822 | ut_error; |
823 | } |
824 | } |
825 | @@ -842,7 +924,7 @@ |
826 | /* In normal mysqld crash recovery we do not try to |
827 | replay file operations */ |
828 | #ifdef UNIV_LOG_LSN_DEBUG |
829 | -@@ -2748,8 +2749,11 @@ |
830 | +@@ -2748,8 +2761,11 @@ |
831 | |
832 | fprintf(stderr, |
833 | "InnoDB: Doing recovery: scanned up to" |
834 | @@ -856,7 +938,7 @@ |
835 | } |
836 | } |
837 | |
838 | -@@ -2854,7 +2858,7 @@ |
839 | +@@ -2854,7 +2870,7 @@ |
840 | "InnoDB: Reading tablespace information" |
841 | " from the .ibd files...\n"); |
842 | |
843 | @@ -865,7 +947,7 @@ |
844 | |
845 | /* If we are using the doublewrite method, we will |
846 | check if there are half-written pages in data files, |
847 | -@@ -2863,12 +2867,14 @@ |
848 | +@@ -2863,12 +2879,14 @@ |
849 | |
850 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
851 | |
852 | @@ -881,7 +963,7 @@ |
853 | } |
854 | } |
855 | |
856 | -@@ -3018,6 +3024,7 @@ |
857 | +@@ -3018,6 +3036,7 @@ |
858 | recv_sys->recovered_lsn = checkpoint_lsn; |
859 | |
860 | srv_start_lsn = checkpoint_lsn; |
861 | @@ -889,7 +971,7 @@ |
862 | } |
863 | |
864 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
865 | -@@ -3299,6 +3306,7 @@ |
866 | +@@ -3299,6 +3318,7 @@ |
867 | that the data dictionary tables will be free of any locks. |
868 | The data dictionary latch should guarantee that there is at |
869 | most one data dictionary transaction active at a time. */ |
870 | @@ -1011,17 +1093,18 @@ |
871 | secondary index entries for merge sort */ |
872 | --- a/storage/innobase/srv/srv0srv.c |
873 | +++ b/storage/innobase/srv/srv0srv.c |
874 | -@@ -399,6 +399,9 @@ |
875 | +@@ -399,6 +399,10 @@ |
876 | |
877 | UNIV_INTERN ulong srv_replication_delay = 0; |
878 | |
879 | +UNIV_INTERN ibool srv_read_only = FALSE; |
880 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
881 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
882 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
883 | /*-------------------------------------------*/ |
884 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
885 | UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; |
886 | -@@ -1078,7 +1081,7 @@ |
887 | +@@ -1078,7 +1082,7 @@ |
888 | } |
889 | |
890 | /* Initialize some INFORMATION SCHEMA internal structures */ |
891 | @@ -1030,7 +1113,7 @@ |
892 | } |
893 | |
894 | /*********************************************************************//** |
895 | -@@ -1089,6 +1092,7 @@ |
896 | +@@ -1089,6 +1093,7 @@ |
897 | /*==========*/ |
898 | { |
899 | os_fast_mutex_free(&srv_conc_mutex); |
900 | @@ -1038,7 +1121,7 @@ |
901 | mem_free(srv_conc_slots); |
902 | srv_conc_slots = NULL; |
903 | |
904 | -@@ -1102,6 +1106,7 @@ |
905 | +@@ -1102,6 +1107,7 @@ |
906 | srv_mysql_table = NULL; |
907 | |
908 | trx_i_s_cache_free(trx_i_s_cache); |
909 | @@ -1046,7 +1129,7 @@ |
910 | } |
911 | |
912 | /*********************************************************************//** |
913 | -@@ -1717,7 +1722,7 @@ |
914 | +@@ -1717,7 +1723,7 @@ |
915 | } |
916 | |
917 | /* Record the lock wait time for this thread */ |
918 | @@ -1264,3 +1347,16 @@ |
919 | |
920 | UNIV_MEM_FREE(buf, n); |
921 | } |
922 | +--- a/configure.cmake |
923 | ++++ b/configure.cmake |
924 | +@@ -149,7 +149,9 @@ |
925 | + SET(CMAKE_REQUIRED_LIBRARIES |
926 | + ${LIBM} ${LIBNSL} ${LIBBIND} ${LIBCRYPT} ${LIBSOCKET} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT} ${LIBRT}) |
927 | + |
928 | +- LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) |
929 | ++ IF(CMAKE_REQUIRED_LIBRARIES) |
930 | ++ LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) |
931 | ++ ENDIF() |
932 | + LINK_LIBRARIES(${CMAKE_THREAD_LIBS_INIT}) |
933 | + |
934 | + OPTION(WITH_LIBWRAP "Compile with tcp wrappers support" OFF) |
935 | |
936 | === modified file 'patches/innodb56.patch' |
937 | --- patches/innodb56.patch 2013-05-03 14:12:58 +0000 |
938 | +++ patches/innodb56.patch 2013-05-08 05:16:27 +0000 |
939 | @@ -336,7 +336,7 @@ |
940 | |
941 | + /* Ignore .isl files on XtraBackup recovery. All tablespaces must be |
942 | + local. */ |
943 | -+ if (!recv_recovery_on) { |
944 | ++ if (srv_backup_mode) { |
945 | /* Check for a link file which locates a remote tablespace. */ |
946 | remote.success = fil_open_linked_file( |
947 | tablename, &remote.filepath, &remote.file); |
948 | @@ -357,7 +357,60 @@ |
949 | ib_logf(IB_LOG_LEVEL_ERROR, |
950 | "The size of single-table tablespace file %s " |
951 | "is only " UINT64PF ", should be at least %lu!", |
952 | -@@ -4263,7 +4390,7 @@ |
953 | +@@ -4243,7 +4370,51 @@ |
954 | + } |
955 | + |
956 | + func_exit: |
957 | +- os_file_close(fsp->file); |
958 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
959 | ++ inconsistencies between the file name and the actual tablespace contents |
960 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
961 | ++ the actual copy operation. */ |
962 | ++ if (srv_backup_mode) { |
963 | ++ |
964 | ++ fil_node_t* node; |
965 | ++ fil_space_t* space; |
966 | ++ |
967 | ++ mutex_enter(&fil_system->mutex); |
968 | ++ |
969 | ++ space = fil_space_get_by_id(fsp->id); |
970 | ++ |
971 | ++ if (space) { |
972 | ++ node = UT_LIST_GET_LAST(space->chain); |
973 | ++ |
974 | ++ /* The handle will be closed by xtrabackup in |
975 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
976 | ++ make sure no one calls fil_node_open_file() |
977 | ++ (i.e. attempts to reopen the tablespace by name) during |
978 | ++ the backup stage. */ |
979 | ++ |
980 | ++ node->open = TRUE; |
981 | ++ node->handle = fsp->file; |
982 | ++ |
983 | ++ /* The following is copied from fil_node_open_file() to |
984 | ++ pass fil_system validaty checks. We cannot use |
985 | ++ fil_node_open_file() directly, as that would re-open the |
986 | ++ file by name and create another file handle. */ |
987 | ++ |
988 | ++ fil_system->n_open++; |
989 | ++ fil_n_file_opened++; |
990 | ++ |
991 | ++ if (fil_space_belongs_in_lru(space)) { |
992 | ++ |
993 | ++ /* Put the node to the LRU list */ |
994 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
995 | ++ } |
996 | ++ } |
997 | ++ |
998 | ++ mutex_exit(&fil_system->mutex); |
999 | ++ } else { |
1000 | ++ |
1001 | ++ os_file_close(fsp->file); |
1002 | ++ } |
1003 | + |
1004 | + #ifdef UNIV_HOTBACKUP |
1005 | + func_exit_after_close: |
1006 | +@@ -4263,7 +4434,7 @@ |
1007 | idea is to read as much good data as we can and jump over bad data. |
1008 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
1009 | of the directory */ |
1010 | @@ -366,7 +419,7 @@ |
1011 | int |
1012 | fil_file_readdir_next_file( |
1013 | /*=======================*/ |
1014 | -@@ -4303,7 +4430,7 @@ |
1015 | +@@ -4303,7 +4474,7 @@ |
1016 | @return DB_SUCCESS or error number */ |
1017 | UNIV_INTERN |
1018 | dberr_t |
1019 | @@ -375,7 +428,7 @@ |
1020 | /*===================================*/ |
1021 | { |
1022 | int ret; |
1023 | -@@ -4359,7 +4486,9 @@ |
1024 | +@@ -4359,7 +4530,9 @@ |
1025 | "%s/%s", fil_path_to_mysql_datadir, dbinfo.name); |
1026 | srv_normalize_path_for_win(dbpath); |
1027 | |
1028 | @@ -386,7 +439,7 @@ |
1029 | |
1030 | if (dbdir != NULL) { |
1031 | |
1032 | -@@ -4380,9 +4509,15 @@ |
1033 | +@@ -4380,9 +4553,15 @@ |
1034 | && (0 == strcmp(fileinfo.name |
1035 | + strlen(fileinfo.name) - 4, |
1036 | ".ibd") |
1037 | @@ -394,7 +447,7 @@ |
1038 | + /* Ignore .isl files on XtraBackup |
1039 | + recovery, all tablespaces must be |
1040 | + local. */ |
1041 | -+ || (!recv_recovery_on && |
1042 | ++ || (srv_backup_mode && |
1043 | + 0 == strcmp(fileinfo.name |
1044 | + strlen(fileinfo.name) - 4, |
1045 | - ".isl"))) { |
1046 | @@ -404,7 +457,7 @@ |
1047 | /* The name ends in .ibd or .isl; |
1048 | try opening the file */ |
1049 | fil_load_single_table_tablespace( |
1050 | -@@ -4538,6 +4673,7 @@ |
1051 | +@@ -4538,6 +4717,7 @@ |
1052 | { |
1053 | fil_space_t* fnamespace; |
1054 | fil_space_t* space; |
1055 | @@ -412,7 +465,7 @@ |
1056 | |
1057 | ut_ad(fil_system); |
1058 | |
1059 | -@@ -4615,6 +4751,10 @@ |
1060 | +@@ -4615,6 +4795,10 @@ |
1061 | if (fnamespace == NULL) { |
1062 | if (print_error_if_does_not_exist) { |
1063 | fil_report_missing_tablespace(name, id); |
1064 | @@ -423,7 +476,7 @@ |
1065 | } |
1066 | } else { |
1067 | ut_print_timestamp(stderr); |
1068 | -@@ -4638,6 +4778,10 @@ |
1069 | +@@ -4638,6 +4822,10 @@ |
1070 | |
1071 | mutex_exit(&fil_system->mutex); |
1072 | |
1073 | @@ -434,7 +487,7 @@ |
1074 | return(FALSE); |
1075 | } |
1076 | |
1077 | -@@ -4728,6 +4872,7 @@ |
1078 | +@@ -4728,6 +4916,7 @@ |
1079 | ulint page_size; |
1080 | ulint pages_added; |
1081 | ibool success; |
1082 | @@ -442,7 +495,7 @@ |
1083 | |
1084 | ut_ad(!srv_read_only_mode); |
1085 | |
1086 | -@@ -4772,13 +4917,17 @@ |
1087 | +@@ -4772,13 +4961,17 @@ |
1088 | goto retry; |
1089 | } |
1090 | |
1091 | @@ -461,7 +514,7 @@ |
1092 | start_page_no = space->size; |
1093 | file_start_page_no = space->size - node->size; |
1094 | |
1095 | -@@ -5024,7 +5173,7 @@ |
1096 | +@@ -5024,7 +5217,7 @@ |
1097 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
1098 | mutex. */ |
1099 | static |
1100 | @@ -470,7 +523,7 @@ |
1101 | fil_node_prepare_for_io( |
1102 | /*====================*/ |
1103 | fil_node_t* node, /*!< in: file node */ |
1104 | -@@ -5044,9 +5193,12 @@ |
1105 | +@@ -5044,9 +5237,12 @@ |
1106 | } |
1107 | |
1108 | if (node->open == FALSE) { |
1109 | @@ -484,7 +537,7 @@ |
1110 | } |
1111 | |
1112 | if (node->n_pending == 0 && fil_space_belongs_in_lru(space)) { |
1113 | -@@ -5058,6 +5210,8 @@ |
1114 | +@@ -5058,6 +5254,8 @@ |
1115 | } |
1116 | |
1117 | node->n_pending++; |
1118 | @@ -493,7 +546,7 @@ |
1119 | } |
1120 | |
1121 | /********************************************************************//** |
1122 | -@@ -5259,6 +5413,16 @@ |
1123 | +@@ -5259,6 +5457,16 @@ |
1124 | |
1125 | ut_ad(mode != OS_AIO_IBUF || space->purpose == FIL_TABLESPACE); |
1126 | |
1127 | @@ -510,7 +563,7 @@ |
1128 | node = UT_LIST_GET_FIRST(space->chain); |
1129 | |
1130 | for (;;) { |
1131 | -@@ -5290,7 +5454,11 @@ |
1132 | +@@ -5290,7 +5498,11 @@ |
1133 | } |
1134 | |
1135 | /* Open file if closed */ |
1136 | @@ -523,7 +576,7 @@ |
1137 | |
1138 | /* Check that at least the start offset is within the bounds of a |
1139 | single-table tablespace, including rollback tablespaces. */ |
1140 | -@@ -6164,6 +6332,7 @@ |
1141 | +@@ -6164,6 +6376,7 @@ |
1142 | return(err); |
1143 | } |
1144 | |
1145 | @@ -531,7 +584,7 @@ |
1146 | /****************************************************************//** |
1147 | Generate redo logs for swapping two .ibd files */ |
1148 | UNIV_INTERN |
1149 | -@@ -6187,4 +6356,4 @@ |
1150 | +@@ -6187,4 +6400,4 @@ |
1151 | 0, 0, new_name, old_name, &mtr); |
1152 | mtr_commit(&mtr); |
1153 | } |
1154 | @@ -674,13 +727,15 @@ |
1155 | Returns TRUE if a single-table tablespace does not exist in the memory cache, |
1156 | --- a/storage/innobase/include/srv0srv.h |
1157 | +++ b/storage/innobase/include/srv0srv.h |
1158 | -@@ -353,6 +353,9 @@ |
1159 | +@@ -353,6 +353,11 @@ |
1160 | extern ulong srv_max_purge_lag_delay; |
1161 | |
1162 | extern ulong srv_replication_delay; |
1163 | + |
1164 | +extern ibool srv_apply_log_only; |
1165 | + |
1166 | ++extern ibool srv_backup_mode; |
1167 | ++ |
1168 | /*-------------------------------------------*/ |
1169 | |
1170 | extern ibool srv_print_innodb_monitor; |
1171 | @@ -755,7 +810,26 @@ |
1172 | || (recv_addr->state == RECV_BEING_PROCESSED) |
1173 | || (recv_addr->state == RECV_PROCESSED)) { |
1174 | |
1175 | -@@ -2413,7 +2415,7 @@ |
1176 | +@@ -1868,6 +1870,18 @@ |
1177 | + ulint zip_size = fil_space_get_zip_size(space); |
1178 | + ulint page_no = recv_addr->page_no; |
1179 | + |
1180 | ++ /* By now we have replayed all DDL log records from the |
1181 | ++ current batch. Check if the space ID is still valid in |
1182 | ++ the entry being processed, and ignore it if it is not.*/ |
1183 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
1184 | ++ |
1185 | ++ ut_a(recv_sys->n_addrs); |
1186 | ++ |
1187 | ++ recv_addr->state = RECV_PROCESSED; |
1188 | ++ recv_sys->n_addrs--; |
1189 | ++ |
1190 | ++ continue; |
1191 | ++ } |
1192 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
1193 | + if (!has_printed) { |
1194 | + ib_logf(IB_LOG_LEVEL_INFO, |
1195 | +@@ -2413,7 +2427,7 @@ |
1196 | || type == MLOG_FILE_RENAME |
1197 | || type == MLOG_FILE_DELETE) { |
1198 | ut_a(space); |
1199 | @@ -764,7 +838,7 @@ |
1200 | if (recv_replay_file_ops) { |
1201 | |
1202 | /* In ibbackup --apply-log, replay an .ibd file |
1203 | -@@ -2436,7 +2438,7 @@ |
1204 | +@@ -2436,7 +2450,7 @@ |
1205 | ut_error; |
1206 | } |
1207 | } |
1208 | @@ -773,7 +847,7 @@ |
1209 | /* In normal mysqld crash recovery we do not try to |
1210 | replay file operations */ |
1211 | #ifdef UNIV_LOG_LSN_DEBUG |
1212 | -@@ -2863,8 +2865,14 @@ |
1213 | +@@ -2863,8 +2877,14 @@ |
1214 | |
1215 | fprintf(stderr, |
1216 | "InnoDB: Doing recovery: scanned up to" |
1217 | @@ -790,7 +864,7 @@ |
1218 | } |
1219 | } |
1220 | |
1221 | -@@ -2964,7 +2972,7 @@ |
1222 | +@@ -2964,7 +2984,7 @@ |
1223 | ib_logf(IB_LOG_LEVEL_INFO, |
1224 | "Reading tablespace information from the .ibd files..."); |
1225 | |
1226 | @@ -799,7 +873,7 @@ |
1227 | |
1228 | /* If we are using the doublewrite method, we will |
1229 | check if there are half-written pages in data files, |
1230 | -@@ -3456,7 +3464,8 @@ |
1231 | +@@ -3456,7 +3476,8 @@ |
1232 | that the data dictionary tables will be free of any locks. |
1233 | The data dictionary latch should guarantee that there is at |
1234 | most one data dictionary transaction active at a time. */ |
1235 | @@ -836,16 +910,18 @@ |
1236 | tested with following crash point */ |
1237 | --- a/storage/innobase/srv/srv0srv.cc |
1238 | +++ b/storage/innobase/srv/srv0srv.cc |
1239 | -@@ -349,6 +349,8 @@ |
1240 | +@@ -349,6 +349,10 @@ |
1241 | |
1242 | UNIV_INTERN ulong srv_replication_delay = 0; |
1243 | |
1244 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
1245 | + |
1246 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
1247 | ++ |
1248 | /*-------------------------------------------*/ |
1249 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
1250 | UNIV_INTERN ulong srv_spin_wait_delay = 6; |
1251 | -@@ -1808,7 +1810,8 @@ |
1252 | +@@ -1808,7 +1812,8 @@ |
1253 | if (ret == SRV_NONE |
1254 | && srv_shutdown_state != SRV_SHUTDOWN_NONE |
1255 | && trx_purge_state() != PURGE_STATE_DISABLED |
1256 | |
1257 | === modified file 'patches/xtradb51.patch' |
1258 | --- patches/xtradb51.patch 2013-04-16 14:29:50 +0000 |
1259 | +++ patches/xtradb51.patch 2013-05-08 05:16:27 +0000 |
1260 | @@ -326,7 +326,60 @@ |
1261 | if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { |
1262 | fprintf(stderr, |
1263 | "InnoDB: Error: the size of single-table tablespace" |
1264 | -@@ -4247,7 +4349,7 @@ |
1265 | +@@ -4236,7 +4338,51 @@ |
1266 | + |
1267 | + fil_node_create(filepath, 0, space_id, FALSE); |
1268 | + func_exit: |
1269 | +- os_file_close(file); |
1270 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
1271 | ++ inconsistencies between the file name and the actual tablespace contents |
1272 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
1273 | ++ the actual copy operation. */ |
1274 | ++ if (srv_backup_mode) { |
1275 | ++ |
1276 | ++ fil_node_t* node; |
1277 | ++ fil_space_t* space; |
1278 | ++ |
1279 | ++ mutex_enter(&fil_system->mutex); |
1280 | ++ |
1281 | ++ space = fil_space_get_by_id(space_id); |
1282 | ++ |
1283 | ++ if (space) { |
1284 | ++ node = UT_LIST_GET_LAST(space->chain); |
1285 | ++ |
1286 | ++ /* The handle will be closed by xtrabackup in |
1287 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
1288 | ++ make sure no one calls fil_node_open_file() |
1289 | ++ (i.e. attempts to reopen the tablespace by name) during |
1290 | ++ the backup stage. */ |
1291 | ++ |
1292 | ++ node->open = TRUE; |
1293 | ++ node->handle = file; |
1294 | ++ |
1295 | ++ /* The following is copied from fil_node_open_file() to |
1296 | ++ pass fil_system validity checks. We cannot use |
1297 | ++ fil_node_open_file() directly, as that would re-open the |
1298 | ++ file by name and create another file handle. */ |
1299 | ++ |
1300 | ++ fil_system->n_open++; |
1301 | ++ |
1302 | ++ if (space->purpose == FIL_TABLESPACE && |
1303 | ++ space->id != 0) { |
1304 | ++ |
1305 | ++ /* Put the node to the LRU list */ |
1306 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
1307 | ++ } |
1308 | ++ } |
1309 | ++ |
1310 | ++ mutex_exit(&fil_system->mutex); |
1311 | ++ } else { |
1312 | ++ |
1313 | ++ os_file_close(file); |
1314 | ++ } |
1315 | + ut_free(buf2); |
1316 | + mem_free(filepath); |
1317 | + } |
1318 | +@@ -4247,7 +4393,7 @@ |
1319 | idea is to read as much good data as we can and jump over bad data. |
1320 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
1321 | of the directory */ |
1322 | @@ -335,7 +388,7 @@ |
1323 | int |
1324 | fil_file_readdir_next_file( |
1325 | /*=======================*/ |
1326 | -@@ -4291,7 +4393,7 @@ |
1327 | +@@ -4291,7 +4437,7 @@ |
1328 | @return DB_SUCCESS or error number */ |
1329 | UNIV_INTERN |
1330 | ulint |
1331 | @@ -344,7 +397,7 @@ |
1332 | /*===================================*/ |
1333 | { |
1334 | int ret; |
1335 | -@@ -4347,7 +4449,9 @@ |
1336 | +@@ -4347,7 +4493,9 @@ |
1337 | dbinfo.name); |
1338 | srv_normalize_path_for_win(dbpath); |
1339 | |
1340 | @@ -355,7 +408,7 @@ |
1341 | |
1342 | if (dbdir != NULL) { |
1343 | /* printf("Opened dir %s\n", dbinfo.name); */ |
1344 | -@@ -4373,8 +4477,11 @@ |
1345 | +@@ -4373,8 +4521,11 @@ |
1346 | ".ibd")) { |
1347 | /* The name ends in .ibd; try opening |
1348 | the file */ |
1349 | @@ -368,7 +421,7 @@ |
1350 | } |
1351 | next_file_item: |
1352 | ret = fil_file_readdir_next_file(&err, |
1353 | -@@ -4546,15 +4653,97 @@ |
1354 | +@@ -4546,15 +4697,97 @@ |
1355 | "InnoDB: in InnoDB data dictionary" |
1356 | " has tablespace id %lu,\n" |
1357 | "InnoDB: but tablespace with that id" |
1358 | @@ -474,7 +527,7 @@ |
1359 | } else { |
1360 | ut_print_timestamp(stderr); |
1361 | fputs(" InnoDB: Error: table ", stderr); |
1362 | -@@ -4953,7 +5142,7 @@ |
1363 | +@@ -4953,7 +5186,7 @@ |
1364 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
1365 | mutex. */ |
1366 | static |
1367 | @@ -483,7 +536,7 @@ |
1368 | fil_node_prepare_for_io( |
1369 | /*====================*/ |
1370 | fil_node_t* node, /*!< in: file node */ |
1371 | -@@ -4973,10 +5162,13 @@ |
1372 | +@@ -4973,10 +5206,13 @@ |
1373 | } |
1374 | |
1375 | if (node->open == FALSE) { |
1376 | @@ -498,7 +551,7 @@ |
1377 | } |
1378 | |
1379 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
1380 | -@@ -4989,6 +5181,8 @@ |
1381 | +@@ -4989,6 +5225,8 @@ |
1382 | } |
1383 | |
1384 | node->n_pending++; |
1385 | @@ -507,7 +560,7 @@ |
1386 | } |
1387 | |
1388 | /********************************************************************//** |
1389 | -@@ -5125,7 +5319,9 @@ |
1390 | +@@ -5125,7 +5363,9 @@ |
1391 | ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE) |
1392 | || !ibuf_bitmap_page(zip_size, block_offset) |
1393 | || sync || is_log); |
1394 | @@ -518,7 +571,7 @@ |
1395 | || ibuf_page(space_id, zip_size, block_offset, NULL)); |
1396 | # endif /* UNIV_LOG_DEBUG */ |
1397 | if (sync) { |
1398 | -@@ -5190,6 +5386,16 @@ |
1399 | +@@ -5190,6 +5430,16 @@ |
1400 | |
1401 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
1402 | |
1403 | @@ -650,13 +703,14 @@ |
1404 | return(buf); |
1405 | --- a/storage/innodb_plugin/include/srv0srv.h |
1406 | +++ b/storage/innodb_plugin/include/srv0srv.h |
1407 | -@@ -226,6 +226,10 @@ |
1408 | +@@ -226,6 +226,11 @@ |
1409 | |
1410 | extern ulong srv_replication_delay; |
1411 | |
1412 | +extern ibool srv_read_only; |
1413 | +extern ibool srv_fake_write; |
1414 | +extern ibool srv_apply_log_only; |
1415 | ++extern ibool srv_backup_mode; |
1416 | + |
1417 | extern long long srv_ibuf_max_size; |
1418 | extern ulint srv_ibuf_active_contract; |
1419 | @@ -826,7 +880,35 @@ |
1420 | ibool |
1421 | log_block_checksum_is_ok_or_old_format( |
1422 | /*===================================*/ |
1423 | -@@ -2369,7 +2369,7 @@ |
1424 | +@@ -1830,6 +1830,18 @@ |
1425 | + ulint zip_size = fil_space_get_zip_size(space); |
1426 | + ulint page_no = recv_addr->page_no; |
1427 | + |
1428 | ++ /* By now we have replayed all DDL log records from the |
1429 | ++ current batch. Check if the space ID is still valid in |
1430 | ++ the entry being processed, and ignore it if it is not.*/ |
1431 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
1432 | ++ |
1433 | ++ ut_a(recv_sys->n_addrs); |
1434 | ++ |
1435 | ++ recv_addr->state = RECV_PROCESSED; |
1436 | ++ recv_sys->n_addrs--; |
1437 | ++ |
1438 | ++ goto next; |
1439 | ++ } |
1440 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
1441 | + if (!has_printed) { |
1442 | + ut_print_timestamp(stderr); |
1443 | +@@ -1863,7 +1875,7 @@ |
1444 | + |
1445 | + mutex_enter(&(recv_sys->mutex)); |
1446 | + } |
1447 | +- |
1448 | ++next: |
1449 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
1450 | + } |
1451 | + |
1452 | +@@ -2369,7 +2381,7 @@ |
1453 | || type == MLOG_FILE_RENAME |
1454 | || type == MLOG_FILE_DELETE) { |
1455 | ut_a(space); |
1456 | @@ -835,7 +917,7 @@ |
1457 | if (recv_replay_file_ops) { |
1458 | |
1459 | /* In ibbackup --apply-log, replay an .ibd file |
1460 | -@@ -2392,7 +2392,7 @@ |
1461 | +@@ -2392,7 +2404,7 @@ |
1462 | ut_error; |
1463 | } |
1464 | } |
1465 | @@ -844,7 +926,7 @@ |
1466 | /* In normal mysqld crash recovery we do not try to |
1467 | replay file operations */ |
1468 | #ifdef UNIV_LOG_LSN_DEBUG |
1469 | -@@ -2809,8 +2809,11 @@ |
1470 | +@@ -2809,8 +2821,11 @@ |
1471 | |
1472 | fprintf(stderr, |
1473 | "InnoDB: Doing recovery: scanned up to" |
1474 | @@ -858,7 +940,7 @@ |
1475 | } |
1476 | } |
1477 | |
1478 | -@@ -2913,7 +2916,7 @@ |
1479 | +@@ -2913,7 +2928,7 @@ |
1480 | "InnoDB: Reading tablespace information" |
1481 | " from the .ibd files...\n"); |
1482 | |
1483 | @@ -867,7 +949,7 @@ |
1484 | |
1485 | /* If we are using the doublewrite method, we will |
1486 | check if there are half-written pages in data files, |
1487 | -@@ -2922,12 +2925,14 @@ |
1488 | +@@ -2922,12 +2937,14 @@ |
1489 | |
1490 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
1491 | |
1492 | @@ -883,7 +965,7 @@ |
1493 | } |
1494 | } |
1495 | |
1496 | -@@ -3095,6 +3100,7 @@ |
1497 | +@@ -3095,6 +3112,7 @@ |
1498 | recv_sys->recovered_lsn = checkpoint_lsn; |
1499 | |
1500 | srv_start_lsn = checkpoint_lsn; |
1501 | @@ -891,7 +973,7 @@ |
1502 | } |
1503 | |
1504 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
1505 | -@@ -3453,6 +3459,7 @@ |
1506 | +@@ -3453,6 +3471,7 @@ |
1507 | that the data dictionary tables will be free of any locks. |
1508 | The data dictionary latch should guarantee that there is at |
1509 | most one data dictionary transaction active at a time. */ |
1510 | @@ -1026,18 +1108,19 @@ |
1511 | /* prototypes for new functions added to ha_innodb.cc */ |
1512 | ibool innobase_get_slow_log(); |
1513 | |
1514 | -@@ -415,6 +410,10 @@ |
1515 | +@@ -415,6 +410,11 @@ |
1516 | |
1517 | UNIV_INTERN ulong srv_replication_delay = 0; |
1518 | |
1519 | +UNIV_INTERN ibool srv_read_only = FALSE; |
1520 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
1521 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
1522 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
1523 | + |
1524 | UNIV_INTERN long long srv_ibuf_max_size = 0; |
1525 | UNIV_INTERN ulint srv_ibuf_active_contract = 0; /* 0:disable 1:enable */ |
1526 | UNIV_INTERN ulint srv_ibuf_accel_rate = 100; |
1527 | -@@ -1065,7 +1064,7 @@ |
1528 | +@@ -1065,7 +1065,7 @@ |
1529 | } |
1530 | |
1531 | /* Initialize some INFORMATION SCHEMA internal structures */ |
1532 | @@ -1046,7 +1129,7 @@ |
1533 | } |
1534 | |
1535 | /*********************************************************************//** |
1536 | -@@ -1076,6 +1075,7 @@ |
1537 | +@@ -1076,6 +1076,7 @@ |
1538 | /*==========*/ |
1539 | { |
1540 | os_fast_mutex_free(&srv_conc_mutex); |
1541 | @@ -1054,7 +1137,7 @@ |
1542 | mem_free(srv_conc_slots); |
1543 | srv_conc_slots = NULL; |
1544 | |
1545 | -@@ -1089,6 +1089,7 @@ |
1546 | +@@ -1089,6 +1090,7 @@ |
1547 | srv_mysql_table = NULL; |
1548 | |
1549 | trx_i_s_cache_free(trx_i_s_cache); |
1550 | @@ -1062,7 +1145,7 @@ |
1551 | } |
1552 | |
1553 | /*********************************************************************//** |
1554 | -@@ -2570,36 +2571,6 @@ |
1555 | +@@ -2570,36 +2572,6 @@ |
1556 | old_sema = sema; |
1557 | } |
1558 | |
1559 | @@ -1143,7 +1226,6 @@ |
1560 | |
1561 | if (srv_auto_extend_last_data_file |
1562 | && sum_of_data_file_sizes < tablespace_size_in_header) { |
1563 | -- |
1564 | + /* extend table space size aligning with header */ |
1565 | + ulint actual_size; |
1566 | + fil_extend_space_to_desired_size(&actual_size, 0, tablespace_size_in_header); |
1567 | @@ -1154,7 +1236,7 @@ |
1568 | + (ulong) actual_size, |
1569 | + (ulong) tablespace_size_in_header); |
1570 | + } |
1571 | -+ |
1572 | + |
1573 | +#ifdef UNDEFINED |
1574 | fprintf(stderr, |
1575 | "InnoDB: Error: tablespace size stored in header" |
1576 | @@ -1431,3 +1513,14 @@ |
1577 | |
1578 | UNIV_MEM_FREE(buf, n); |
1579 | } |
1580 | +--- a/configure.in |
1581 | ++++ b/configure.in |
1582 | +@@ -22,7 +22,7 @@ |
1583 | + AM_INIT_AUTOMAKE([1.9 tar-ustar]) |
1584 | + AC_PROG_LIBTOOL |
1585 | + |
1586 | +-AM_CONFIG_HEADER([include/config.h]) |
1587 | ++AC_CONFIG_HEADERS([include/config.h]) |
1588 | + |
1589 | + # Request support for automake silent-rules if available. |
1590 | + # Default to verbose output. One can use the configure-time |
1591 | |
1592 | === modified file 'patches/xtradb55.patch' |
1593 | --- patches/xtradb55.patch 2013-04-16 14:29:50 +0000 |
1594 | +++ patches/xtradb55.patch 2013-05-08 05:16:27 +0000 |
1595 | @@ -325,7 +325,60 @@ |
1596 | if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { |
1597 | fprintf(stderr, |
1598 | "InnoDB: Error: the size of single-table tablespace" |
1599 | -@@ -4299,7 +4402,7 @@ |
1600 | +@@ -4288,7 +4391,51 @@ |
1601 | + |
1602 | + fil_node_create(filepath, 0, space_id, FALSE); |
1603 | + func_exit: |
1604 | +- os_file_close(file); |
1605 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
1606 | ++ inconsistencies between the file name and the actual tablespace contents |
1607 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
1608 | ++ the actual copy operation. */ |
1609 | ++ if (srv_backup_mode) { |
1610 | ++ |
1611 | ++ fil_node_t* node; |
1612 | ++ fil_space_t* space; |
1613 | ++ |
1614 | ++ mutex_enter(&fil_system->mutex); |
1615 | ++ |
1616 | ++ space = fil_space_get_by_id(space_id); |
1617 | ++ |
1618 | ++ if (space) { |
1619 | ++ node = UT_LIST_GET_LAST(space->chain); |
1620 | ++ |
1621 | ++ /* The handle will be closed by xtrabackup in |
1622 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
1623 | ++ make sure no one calls fil_node_open_file() |
1624 | ++ (i.e. attempts to reopen the tablespace by name) during |
1625 | ++ the backup stage. */ |
1626 | ++ |
1627 | ++ node->open = TRUE; |
1628 | ++ node->handle = file; |
1629 | ++ |
1630 | ++ /* The following is copied from fil_node_open_file() to |
1631 | ++ pass fil_system validity checks. We cannot use |
1632 | ++ fil_node_open_file() directly, as that would re-open the |
1633 | ++ file by name and create another file handle. */ |
1634 | ++ |
1635 | ++ fil_system->n_open++; |
1636 | ++ |
1637 | ++ if (space->purpose == FIL_TABLESPACE && |
1638 | ++ space->id != 0) { |
1639 | ++ |
1640 | ++ /* Put the node to the LRU list */ |
1641 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
1642 | ++ } |
1643 | ++ } |
1644 | ++ |
1645 | ++ mutex_exit(&fil_system->mutex); |
1646 | ++ } else { |
1647 | ++ |
1648 | ++ os_file_close(file); |
1649 | ++ } |
1650 | + ut_free(buf2); |
1651 | + mem_free(filepath); |
1652 | + } |
1653 | +@@ -4299,7 +4446,7 @@ |
1654 | idea is to read as much good data as we can and jump over bad data. |
1655 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
1656 | of the directory */ |
1657 | @@ -334,7 +387,7 @@ |
1658 | int |
1659 | fil_file_readdir_next_file( |
1660 | /*=======================*/ |
1661 | -@@ -4343,7 +4446,7 @@ |
1662 | +@@ -4343,7 +4490,7 @@ |
1663 | @return DB_SUCCESS or error number */ |
1664 | UNIV_INTERN |
1665 | ulint |
1666 | @@ -343,7 +396,7 @@ |
1667 | /*===================================*/ |
1668 | { |
1669 | int ret; |
1670 | -@@ -4399,7 +4502,9 @@ |
1671 | +@@ -4399,7 +4546,9 @@ |
1672 | dbinfo.name); |
1673 | srv_normalize_path_for_win(dbpath); |
1674 | |
1675 | @@ -354,7 +407,7 @@ |
1676 | |
1677 | if (dbdir != NULL) { |
1678 | /* printf("Opened dir %s\n", dbinfo.name); */ |
1679 | -@@ -4425,8 +4530,11 @@ |
1680 | +@@ -4425,8 +4574,11 @@ |
1681 | ".ibd")) { |
1682 | /* The name ends in .ibd; try opening |
1683 | the file */ |
1684 | @@ -367,7 +420,7 @@ |
1685 | } |
1686 | next_file_item: |
1687 | ret = fil_file_readdir_next_file(&err, |
1688 | -@@ -4598,15 +4706,97 @@ |
1689 | +@@ -4598,15 +4750,97 @@ |
1690 | "InnoDB: in InnoDB data dictionary" |
1691 | " has tablespace id %lu,\n" |
1692 | "InnoDB: but tablespace with that id" |
1693 | @@ -473,7 +526,7 @@ |
1694 | } else { |
1695 | ut_print_timestamp(stderr); |
1696 | fputs(" InnoDB: Error: table ", stderr); |
1697 | -@@ -5005,7 +5195,7 @@ |
1698 | +@@ -5005,7 +5239,7 @@ |
1699 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
1700 | mutex. */ |
1701 | static |
1702 | @@ -482,7 +535,7 @@ |
1703 | fil_node_prepare_for_io( |
1704 | /*====================*/ |
1705 | fil_node_t* node, /*!< in: file node */ |
1706 | -@@ -5025,10 +5215,13 @@ |
1707 | +@@ -5025,10 +5259,13 @@ |
1708 | } |
1709 | |
1710 | if (node->open == FALSE) { |
1711 | @@ -497,7 +550,7 @@ |
1712 | } |
1713 | |
1714 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
1715 | -@@ -5041,6 +5234,8 @@ |
1716 | +@@ -5041,6 +5278,8 @@ |
1717 | } |
1718 | |
1719 | node->n_pending++; |
1720 | @@ -506,7 +559,7 @@ |
1721 | } |
1722 | |
1723 | /********************************************************************//** |
1724 | -@@ -5240,6 +5435,16 @@ |
1725 | +@@ -5240,6 +5479,16 @@ |
1726 | |
1727 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
1728 | |
1729 | @@ -660,7 +713,7 @@ |
1730 | extern char srv_adaptive_flushing; |
1731 | |
1732 | |
1733 | -@@ -247,6 +246,10 @@ |
1734 | +@@ -247,6 +246,11 @@ |
1735 | extern ulint srv_dict_size_limit; |
1736 | |
1737 | extern ulint srv_lazy_drop_table; |
1738 | @@ -668,6 +721,7 @@ |
1739 | +extern ibool srv_read_only; |
1740 | +extern ibool srv_fake_write; |
1741 | +extern ibool srv_apply_log_only; |
1742 | ++extern ibool srv_backup_mode; |
1743 | /*-------------------------------------------*/ |
1744 | |
1745 | extern ulint srv_n_rows_inserted; |
1746 | @@ -790,7 +844,35 @@ |
1747 | ibool |
1748 | log_block_checksum_is_ok_or_old_format( |
1749 | /*===================================*/ |
1750 | -@@ -2380,7 +2380,7 @@ |
1751 | +@@ -1842,6 +1842,18 @@ |
1752 | + ulint zip_size = fil_space_get_zip_size(space); |
1753 | + ulint page_no = recv_addr->page_no; |
1754 | + |
1755 | ++ /* By now we have replayed all DDL log records from the |
1756 | ++ current batch. Check if the space ID is still valid in |
1757 | ++ the entry being processed, and ignore it if it is not.*/ |
1758 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
1759 | ++ |
1760 | ++ ut_a(recv_sys->n_addrs); |
1761 | ++ |
1762 | ++ recv_addr->state = RECV_PROCESSED; |
1763 | ++ recv_sys->n_addrs--; |
1764 | ++ |
1765 | ++ goto next; |
1766 | ++ } |
1767 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
1768 | + if (!has_printed) { |
1769 | + ut_print_timestamp(stderr); |
1770 | +@@ -1875,7 +1887,7 @@ |
1771 | + |
1772 | + mutex_enter(&(recv_sys->mutex)); |
1773 | + } |
1774 | +- |
1775 | ++next: |
1776 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
1777 | + } |
1778 | + |
1779 | +@@ -2380,7 +2392,7 @@ |
1780 | || type == MLOG_FILE_RENAME |
1781 | || type == MLOG_FILE_DELETE) { |
1782 | ut_a(space); |
1783 | @@ -799,7 +881,7 @@ |
1784 | if (recv_replay_file_ops) { |
1785 | |
1786 | /* In ibbackup --apply-log, replay an .ibd file |
1787 | -@@ -2403,7 +2403,7 @@ |
1788 | +@@ -2403,7 +2415,7 @@ |
1789 | ut_error; |
1790 | } |
1791 | } |
1792 | @@ -808,7 +890,7 @@ |
1793 | /* In normal mysqld crash recovery we do not try to |
1794 | replay file operations */ |
1795 | #ifdef UNIV_LOG_LSN_DEBUG |
1796 | -@@ -2820,8 +2820,11 @@ |
1797 | +@@ -2820,8 +2832,11 @@ |
1798 | |
1799 | fprintf(stderr, |
1800 | "InnoDB: Doing recovery: scanned up to" |
1801 | @@ -822,7 +904,7 @@ |
1802 | } |
1803 | } |
1804 | |
1805 | -@@ -2926,7 +2929,7 @@ |
1806 | +@@ -2926,7 +2941,7 @@ |
1807 | "InnoDB: Reading tablespace information" |
1808 | " from the .ibd files...\n"); |
1809 | |
1810 | @@ -831,7 +913,7 @@ |
1811 | |
1812 | /* If we are using the doublewrite method, we will |
1813 | check if there are half-written pages in data files, |
1814 | -@@ -2935,12 +2938,14 @@ |
1815 | +@@ -2935,12 +2950,14 @@ |
1816 | |
1817 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
1818 | |
1819 | @@ -847,7 +929,7 @@ |
1820 | } |
1821 | } |
1822 | |
1823 | -@@ -3109,6 +3114,7 @@ |
1824 | +@@ -3109,6 +3126,7 @@ |
1825 | recv_sys->recovered_lsn = checkpoint_lsn; |
1826 | |
1827 | srv_start_lsn = checkpoint_lsn; |
1828 | @@ -855,7 +937,7 @@ |
1829 | } |
1830 | |
1831 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
1832 | -@@ -3474,6 +3480,7 @@ |
1833 | +@@ -3474,6 +3492,7 @@ |
1834 | that the data dictionary tables will be free of any locks. |
1835 | The data dictionary latch should guarantee that there is at |
1836 | most one data dictionary transaction active at a time. */ |
1837 | @@ -1017,7 +1099,7 @@ |
1838 | |
1839 | /* Try to flush dirty pages so as to avoid IO bursts at |
1840 | the checkpoints. */ |
1841 | -@@ -457,6 +451,10 @@ |
1842 | +@@ -457,6 +451,11 @@ |
1843 | UNIV_INTERN ulint srv_dict_size_limit = 0; |
1844 | |
1845 | UNIV_INTERN ulint srv_lazy_drop_table = 0; |
1846 | @@ -1025,10 +1107,11 @@ |
1847 | +UNIV_INTERN ibool srv_read_only = FALSE; |
1848 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
1849 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
1850 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
1851 | /*-------------------------------------------*/ |
1852 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
1853 | UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; |
1854 | -@@ -1137,7 +1135,7 @@ |
1855 | +@@ -1137,7 +1136,7 @@ |
1856 | } |
1857 | |
1858 | /* Initialize some INFORMATION SCHEMA internal structures */ |
1859 | @@ -1037,7 +1120,7 @@ |
1860 | } |
1861 | |
1862 | /*********************************************************************//** |
1863 | -@@ -1148,6 +1146,7 @@ |
1864 | +@@ -1148,6 +1147,7 @@ |
1865 | /*==========*/ |
1866 | { |
1867 | os_fast_mutex_free(&srv_conc_mutex); |
1868 | @@ -1045,7 +1128,7 @@ |
1869 | mem_free(srv_conc_slots); |
1870 | srv_conc_slots = NULL; |
1871 | |
1872 | -@@ -1161,6 +1160,7 @@ |
1873 | +@@ -1161,6 +1161,7 @@ |
1874 | srv_mysql_table = NULL; |
1875 | |
1876 | trx_i_s_cache_free(trx_i_s_cache); |
1877 | @@ -1053,7 +1136,7 @@ |
1878 | } |
1879 | |
1880 | /*********************************************************************//** |
1881 | -@@ -1886,7 +1886,7 @@ |
1882 | +@@ -1886,7 +1887,7 @@ |
1883 | } |
1884 | |
1885 | /* Record the lock wait time for this thread */ |
1886 | @@ -1062,7 +1145,7 @@ |
1887 | } |
1888 | |
1889 | if (trx->was_chosen_as_deadlock_victim) { |
1890 | -@@ -2842,36 +2842,6 @@ |
1891 | +@@ -2842,36 +2843,6 @@ |
1892 | old_sema = sema; |
1893 | } |
1894 | |
1895 | |
1896 | === modified file 'src/xtrabackup.cc' |
1897 | --- src/xtrabackup.cc 2013-05-03 14:12:58 +0000 |
1898 | +++ src/xtrabackup.cc 2013-05-08 05:16:27 +0000 |
1899 | @@ -4035,6 +4035,55 @@ |
1900 | |
1901 | } |
1902 | |
1903 | +/**********************************************************************//** |
1904 | +Closes a file. */ |
1905 | +static |
1906 | +void |
1907 | +xb_fil_node_close_file( |
1908 | +/*===================*/ |
1909 | + fil_node_t* node) /*!< in: file node */ |
1910 | +{ |
1911 | + ibool ret; |
1912 | + |
1913 | + mutex_enter(&fil_system->mutex); |
1914 | + |
1915 | + ut_ad(node); |
1916 | + ut_a(node->n_pending == 0); |
1917 | + ut_a(node->n_pending_flushes == 0); |
1918 | +#if MYSQL_VERSION_ID >= 50600 |
1919 | + ut_a(!node->being_extended); |
1920 | +#endif |
1921 | + |
1922 | + if (!node->open) { |
1923 | + |
1924 | + mutex_exit(&fil_system->mutex); |
1925 | + |
1926 | + return; |
1927 | + } |
1928 | + |
1929 | + ret = os_file_close(node->handle); |
1930 | + ut_a(ret); |
1931 | + |
1932 | + node->open = FALSE; |
1933 | + |
1934 | + ut_a(fil_system->n_open > 0); |
1935 | + fil_system->n_open--; |
1936 | +#if MYSQL_VERSION_ID >= 50600 |
1937 | + fil_n_file_opened--; |
1938 | +#endif |
1939 | + |
1940 | + if (node->space->purpose == FIL_TABLESPACE && |
1941 | + !trx_sys_sys_space(node->space->id)) { |
1942 | + |
1943 | + ut_a(UT_LIST_GET_LEN(fil_system->LRU) > 0); |
1944 | + |
1945 | + /* The node is in the LRU list, remove it */ |
1946 | + UT_LIST_REMOVE(LRU, fil_system->LRU, node); |
1947 | + } |
1948 | + |
1949 | + mutex_exit(&fil_system->mutex); |
1950 | +} |
1951 | + |
1952 | /* TODO: We may tune the behavior (e.g. by fil_aio)*/ |
1953 | #define COPY_CHUNK 64 |
1954 | |
1955 | @@ -4042,7 +4091,6 @@ |
1956 | my_bool |
1957 | xtrabackup_copy_datafile(fil_node_t* node, uint thread_n, ds_ctxt_t *ds_ctxt) |
1958 | { |
1959 | - os_file_t src_file = XB_FILE_UNDEFINED; |
1960 | MY_STAT src_stat; |
1961 | char dst_name[FN_REFLEN]; |
1962 | char meta_name[FN_REFLEN]; |
1963 | @@ -4093,34 +4141,47 @@ |
1964 | strncpy(dst_name, xb_get_relative_path(node_path, is_system), |
1965 | sizeof(dst_name)); |
1966 | |
1967 | - /* open src_file*/ |
1968 | - src_file = xb_file_create_no_error_handling(node_path, |
1969 | - OS_FILE_OPEN, |
1970 | - OS_FILE_READ_ONLY, |
1971 | - &success); |
1972 | - if (!success) { |
1973 | - /* The following call prints an error message */ |
1974 | - os_file_get_last_error(TRUE); |
1975 | - |
1976 | - msg("[%02u] xtrabackup: Warning: cannot open %s\n" |
1977 | - "[%02u] xtrabackup: Warning: We assume the " |
1978 | - "table was dropped or renamed during " |
1979 | - "xtrabackup execution and ignore the file.\n", |
1980 | - thread_n, node_path, thread_n); |
1981 | - goto skip; |
1982 | + /* We should already have a tablespace handle created by |
1983 | + fil_load_single_table_tablespace() unless it is a system tablespace. */ |
1984 | + if (is_system) { |
1985 | + |
1986 | + node->handle = |
1987 | + xb_file_create_no_error_handling(node_path, |
1988 | + OS_FILE_OPEN, |
1989 | + OS_FILE_READ_ONLY, |
1990 | + &success); |
1991 | + if (!success) { |
1992 | + |
1993 | + msg("[%02u] xtrabackup: error: cannot open " |
1994 | + "system tablespace %s\n", thread_n, node_path); |
1995 | + goto error; |
1996 | + } |
1997 | + |
1998 | + mutex_enter(&fil_system->mutex); |
1999 | + |
2000 | + node->open = TRUE; |
2001 | + |
2002 | + fil_system->n_open++; |
2003 | +#if MYSQL_VERSION_ID >= 50600 |
2004 | + fil_n_file_opened++; |
2005 | +#endif |
2006 | + |
2007 | + mutex_exit(&fil_system->mutex); |
2008 | } |
2009 | |
2010 | - xb_file_set_nocache(src_file, node_path, "OPEN"); |
2011 | + ut_ad(node->open); |
2012 | + |
2013 | + xb_file_set_nocache(node->handle, node_path, "OPEN"); |
2014 | |
2015 | #ifdef USE_POSIX_FADVISE |
2016 | - posix_fadvise(src_file, 0, 0, POSIX_FADV_SEQUENTIAL); |
2017 | + posix_fadvise(node->handle, 0, 0, POSIX_FADV_SEQUENTIAL); |
2018 | #endif |
2019 | |
2020 | #ifndef INNODB_VERSION_SHORT |
2021 | page_size = UNIV_PAGE_SIZE; |
2022 | page_size_shift = UNIV_PAGE_SIZE_SHIFT; |
2023 | #else |
2024 | - info.zip_size = xb_get_zip_size(src_file); |
2025 | + info.zip_size = xb_get_zip_size(node->handle); |
2026 | if (info.zip_size == ULINT_UNDEFINED) { |
2027 | goto skip; |
2028 | } else if (info.zip_size) { |
2029 | @@ -4164,10 +4225,10 @@ |
2030 | } else |
2031 | info.page_size = 0; |
2032 | |
2033 | - if (my_stat(node_path, &src_stat, MYF(MY_WME)) == NULL) { |
2034 | + if (my_fstat(node->handle, &src_stat, MYF(MY_WME))) { |
2035 | msg("[%02u] xtrabackup: Warning: cannot stat %s\n", |
2036 | thread_n, node_path); |
2037 | - goto skip; |
2038 | + goto error; |
2039 | } |
2040 | dstfile = ds->open(ds_ctxt, dst_name, &src_stat); |
2041 | if (dstfile == NULL) { |
2042 | @@ -4197,7 +4258,7 @@ |
2043 | * page_size + UNIV_PAGE_SIZE)); |
2044 | page = static_cast<byte *>(ut_align(buf2, UNIV_PAGE_SIZE)); |
2045 | |
2046 | - success = xb_os_file_read(src_file, page, 0, UNIV_PAGE_SIZE); |
2047 | + success = xb_os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE); |
2048 | if (!success) { |
2049 | goto error; |
2050 | } |
2051 | @@ -4218,13 +4279,13 @@ |
2052 | read_retry: |
2053 | xtrabackup_io_throttling(); |
2054 | |
2055 | - success = xb_os_file_read(src_file, page, offset, chunk); |
2056 | + success = xb_os_file_read(node->handle, page, offset, chunk); |
2057 | if (!success) { |
2058 | goto error; |
2059 | } |
2060 | |
2061 | #ifdef USE_POSIX_FADVISE |
2062 | - posix_fadvise(src_file, 0, 0, POSIX_FADV_DONTNEED); |
2063 | + posix_fadvise(node->handle, 0, 0, POSIX_FADV_DONTNEED); |
2064 | #endif |
2065 | |
2066 | /* check corruption and retry */ |
2067 | @@ -4349,17 +4410,17 @@ |
2068 | |
2069 | /* close */ |
2070 | msg("[%02u] ...done\n", thread_n); |
2071 | - if (!node->open) { |
2072 | - os_file_close(src_file); |
2073 | - } |
2074 | + |
2075 | + xb_fil_node_close_file(node); |
2076 | + |
2077 | ds->close(dstfile); |
2078 | if (incremental_buffer_base) |
2079 | ut_free(incremental_buffer_base); |
2080 | ut_free(buf2); |
2081 | return(FALSE); |
2082 | error: |
2083 | - if (src_file != XB_FILE_UNDEFINED && !node->open) |
2084 | - os_file_close(src_file); |
2085 | + xb_fil_node_close_file(node); |
2086 | + |
2087 | if (dstfile != NULL) |
2088 | ds->close(dstfile); |
2089 | if (incremental_buffer_base) |
2090 | @@ -4371,8 +4432,8 @@ |
2091 | return(TRUE); /*ERROR*/ |
2092 | |
2093 | skip: |
2094 | - if (src_file != XB_FILE_UNDEFINED && !node->open) |
2095 | - os_file_close(src_file); |
2096 | + xb_fil_node_close_file(node); |
2097 | + |
2098 | if (dstfile != NULL) |
2099 | ds->close(dstfile); |
2100 | if (incremental_buffer_base) |
2101 | @@ -4789,7 +4850,7 @@ |
2102 | srv_n_file_io_threads, |
2103 | SRV_MAX_N_PENDING_SYNC_IOS); |
2104 | |
2105 | - fil_init(srv_max_n_open_files); |
2106 | + fil_init(LONG_MAX); |
2107 | #else |
2108 | #if MYSQL_VERSION_ID >= 50600 |
2109 | srv_n_file_io_threads = srv_n_read_io_threads; |
2110 | @@ -4803,8 +4864,7 @@ |
2111 | srv_n_write_io_threads, |
2112 | SRV_MAX_N_PENDING_SYNC_IOS); |
2113 | |
2114 | - fil_init(srv_file_per_table ? 50000 : 5000, |
2115 | - srv_max_n_open_files); |
2116 | + fil_init(srv_file_per_table ? 50000 : 5000, LONG_MAX); |
2117 | #endif |
2118 | |
2119 | fsp_init(); |
2120 | @@ -4848,11 +4908,6 @@ |
2121 | return(DB_ERROR); |
2122 | } |
2123 | |
2124 | - err = fil_load_single_table_tablespaces(xb_check_if_open_tablespace); |
2125 | - if (err != DB_SUCCESS) { |
2126 | - return(err); |
2127 | - } |
2128 | - |
2129 | #if MYSQL_VERSION_ID >= 50600 |
2130 | /* Add separate undo tablespaces to fil_system */ |
2131 | |
2132 | @@ -4865,6 +4920,15 @@ |
2133 | } |
2134 | #endif |
2135 | |
2136 | + /* It is important to call fil_load_single_table_tablespace() after |
2137 | + srv_undo_tablespaces_init(), because fil_is_user_tablespace_id() * |
2138 | + relies on srv_undo_tablespaces_open to be properly initialized */ |
2139 | + |
2140 | + err = fil_load_single_table_tablespaces(xb_check_if_open_tablespace); |
2141 | + if (err != DB_SUCCESS) { |
2142 | + return(err); |
2143 | + } |
2144 | + |
2145 | return(DB_SUCCESS); |
2146 | } |
2147 | |
2148 | @@ -5278,6 +5342,8 @@ |
2149 | srv_read_only = TRUE; |
2150 | #endif |
2151 | |
2152 | + srv_backup_mode = TRUE; |
2153 | + |
2154 | /* initialize components */ |
2155 | if(innodb_init_param()) |
2156 | exit(EXIT_FAILURE); |
2157 | |
2158 | === modified file 'test/inc/common.sh' |
2159 | --- test/inc/common.sh 2013-05-01 20:09:28 +0000 |
2160 | +++ test/inc/common.sh 2013-05-08 05:16:27 +0000 |
2161 | @@ -442,6 +442,25 @@ |
2162 | $MYSQL $MYSQL_ARGS -Ns -e "CHECKSUM TABLE $2 EXTENDED" $1 | awk {'print $2'} |
2163 | } |
2164 | |
2165 | +########################################################################## |
2166 | +# Dumps a given database using mysqldump # |
2167 | +########################################################################## |
2168 | +function record_db_state() |
2169 | +{ |
2170 | + $MYSQLDUMP $MYSQL_ARGS -t --compact $1 >"$topdir/tmp/$1_old.sql" |
2171 | +} |
2172 | + |
2173 | + |
2174 | +########################################################################## |
2175 | +# Compares the current dump of a given database with a state previously # |
2176 | +# captured with record_db_state(). # |
2177 | +########################################################################## |
2178 | +function verify_db_state() |
2179 | +{ |
2180 | + $MYSQLDUMP $MYSQL_ARGS -t --compact $1 >"$topdir/tmp/$1_new.sql" |
2181 | + diff -u "$topdir/tmp/$1_old.sql" "$topdir/tmp/$1_new.sql" |
2182 | +} |
2183 | + |
2184 | ######################################################################## |
2185 | # Workarounds for a bug in grep 2.10 when grep -q file > file would |
2186 | # result in a failure. |
2187 | |
2188 | === renamed file 'test/t/bug722638.sh' => 'test/t/ddl.sh' |
2189 | --- test/t/bug722638.sh 2012-06-04 18:29:48 +0000 |
2190 | +++ test/t/ddl.sh 2013-05-08 05:16:27 +0000 |
2191 | @@ -1,7 +1,9 @@ |
2192 | -######################################################################## |
2193 | -# Bug #722638: xtrabackup: taking backup while tables are droped and |
2194 | +############################################################################ |
2195 | +# Bug #722638: xtrabackup: taking backup while tables are droped and |
2196 | # created breaks backup |
2197 | -######################################################################## |
2198 | +# |
2199 | +# Bug #1079700: Issues with renaming/rotating tables during the backup stage |
2200 | +############################################################################ |
2201 | |
2202 | . inc/common.sh |
2203 | |
2204 | @@ -10,7 +12,11 @@ |
2205 | exit $SKIPPED_EXIT_CODE |
2206 | fi |
2207 | |
2208 | -start_server --innodb_file_per_table |
2209 | +MYSQLD_EXTRA_MY_CNF_OPTS=" |
2210 | +innodb_file_per_table |
2211 | +" |
2212 | + |
2213 | +start_server |
2214 | |
2215 | run_cmd $MYSQL $MYSQL_ARGS test <<EOF |
2216 | |
2217 | @@ -26,8 +32,19 @@ |
2218 | CREATE TABLE t4_old(a INT) ENGINE=InnoDB; |
2219 | INSERT INTO t4_old VALUES (1), (2), (3); |
2220 | |
2221 | +CREATE TABLE t5(a INT) ENGINE=InnoDB; |
2222 | +INSERT INTO t5 VALUES (1), (2), (3); |
2223 | + |
2224 | +CREATE TABLE t6(c CHAR(1)) ENGINE=InnoDB; |
2225 | +INSERT INTO t6 VALUES ('a'), ('b'), ('c'); |
2226 | + |
2227 | EOF |
2228 | |
2229 | +# Make a checkpoint so that original tablespace creation events are not in the |
2230 | +# xtrabackup log |
2231 | +shutdown_server |
2232 | +start_server |
2233 | + |
2234 | mkdir -p $topdir/backup |
2235 | |
2236 | # Backup |
2237 | @@ -70,13 +87,18 @@ |
2238 | ALTER TABLE t4_old RENAME t4; |
2239 | INSERT INTO t4 VALUES (7), (8), (9); |
2240 | |
2241 | +INSERT INTO t5 VALUES (4), (5), (6); |
2242 | +INSERT INTO t6 VALUES ('d'), ('e'), ('f'); |
2243 | + |
2244 | +# Rotate tables t5 and t6 |
2245 | +RENAME TABLE t5 TO temp, t6 TO t5, temp TO t6; |
2246 | + |
2247 | +INSERT INTO t5 VALUES ('g'), ('h'), ('i'); |
2248 | +INSERT INTO t6 VALUES (7), (8), (9); |
2249 | + |
2250 | EOF |
2251 | |
2252 | -# Calculate checksums |
2253 | -checksum_t1=`checksum_table test t1` |
2254 | -checksum_t2=`checksum_table test t2` |
2255 | -checksum_t3=`checksum_table test t3` |
2256 | -checksum_t4=`checksum_table test t4` |
2257 | +record_db_state test |
2258 | |
2259 | # Resume xtrabackup |
2260 | vlog "Resuming xtrabackup" |
2261 | @@ -84,6 +106,8 @@ |
2262 | |
2263 | run_cmd wait $job_pid |
2264 | |
2265 | +# exit 1 |
2266 | + |
2267 | # Prepare |
2268 | xtrabackup --datadir=$mysql_datadir --prepare --target-dir=$topdir/backup |
2269 | |
2270 | @@ -94,25 +118,7 @@ |
2271 | $mysql_datadir/test/*.ibd |
2272 | cp -r $topdir/backup/* $mysql_datadir |
2273 | |
2274 | -start_server --innodb_file_per_table |
2275 | - |
2276 | -# Verify checksums |
2277 | -checksum_t1_new=`checksum_table test t1` |
2278 | -checksum_t2_new=`checksum_table test t2` |
2279 | -checksum_t3_new=`checksum_table test t3` |
2280 | -checksum_t4_new=`checksum_table test t4` |
2281 | -vlog "Checksums (old/new):" |
2282 | -vlog "t1: $checksum_t1/$checksum_t1_new" |
2283 | -vlog "t2: $checksum_t2/$checksum_t2_new" |
2284 | -vlog "t3: $checksum_t3/$checksum_t3_new" |
2285 | -vlog "t4: $checksum_t4/$checksum_t4_new" |
2286 | - |
2287 | -if [ "$checksum_t1" = "$checksum_t1_new" -a \ |
2288 | - "$checksum_t2" = "$checksum_t2_new" -a \ |
2289 | - "$checksum_t3" = "$checksum_t3_new" -a \ |
2290 | - "$checksum_t4" = "$checksum_t4_new" ]; then |
2291 | - exit 0 |
2292 | -fi |
2293 | - |
2294 | -vlog "Checksums do not match" |
2295 | -exit -1 |
2296 | +start_server |
2297 | + |
2298 | +# Verify backup |
2299 | +verify_db_state test |
2300 | |
2301 | === modified file 'test/testrun.sh' |
2302 | --- test/testrun.sh 2013-04-27 18:46:54 +0000 |
2303 | +++ test/testrun.sh 2013-05-08 05:16:27 +0000 |
2304 | @@ -70,6 +70,7 @@ |
2305 | find_program MYSQLD mysqld $MYSQL_BASEDIR/bin/ $MYSQL_BASEDIR/libexec |
2306 | find_program MYSQL mysql $MYSQL_BASEDIR/bin |
2307 | find_program MYSQLADMIN mysqladmin $MYSQL_BASEDIR/bin |
2308 | + find_program MYSQLDUMP mysqldump $MYSQL_BASEDIR/bin |
2309 | |
2310 | # Check if we are running from a source tree and, if so, set PATH |
2311 | # appropriately |
2312 | @@ -85,9 +86,10 @@ |
2313 | else |
2314 | LD_LIBRARY_PATH=$MYSQL_BASEDIR/lib/mysql:$LD_LIBRARY_PATH |
2315 | fi |
2316 | + DYLD_LIBRARY_PATH="$LD_LIBRARY_PATH" |
2317 | |
2318 | export TEST_BASEDIR PORT_BASE TAR MYSQL_BASEDIR MYSQL MYSQLD MYSQLADMIN \ |
2319 | -MYSQL_INSTALL_DB PATH LD_LIBRARY_PATH |
2320 | +MYSQL_INSTALL_DB PATH LD_LIBRARY_PATH DYLD_LIBRARY_PATH MYSQLDUMP |
2321 | } |
2322 | |
2323 | |
2324 | |
2325 | === modified file 'utils/build.sh' |
2326 | --- utils/build.sh 2013-04-30 07:33:04 +0000 |
2327 | +++ utils/build.sh 2013-05-08 05:16:27 +0000 |
2328 | @@ -44,7 +44,13 @@ |
2329 | -DUNIV_DEBUG_THREAD_CREATION -DUNIV_DEBUG_LOCK_VALIDATE -DUNIV_DEBUG_PRINT \ |
2330 | -DUNIV_DEBUG_FILE_ACCESS -DUNIV_SEARCH_DEBUG -DUNIV_LOG_LSN_DEBUG \ |
2331 | -DUNIV_ZIP_DEBUG -DUNIV_AHI_DEBUG -DUNIV_SQL_DEBUG -DUNIV_AIO_DEBUG \ |
2332 | --DUNIV_LRU_DEBUG -DUNIV_BUF_DEBUG -DUNIV_HASH_DEBUG -DUNIV_LIST_DEBUG -DUNIV_IBUF_DEBUG" |
2333 | +-DUNIV_LRU_DEBUG -DUNIV_BUF_DEBUG -DUNIV_HASH_DEBUG -DUNIV_IBUF_DEBUG" |
2334 | + |
2335 | + if [ "$type" = "innodb56" ] |
2336 | + then |
2337 | + innodb_extra_debug="$innodb_extra_debug -DUNIV_LIST_DEBUG" |
2338 | + fi |
2339 | + |
2340 | export CFLAGS="$CFLAGS -g -O0 $innodb_extra_debug -DSAFE_MUTEX -DSAFEMALLOC" |
2341 | export CXXFLAGS="$CXXFLAGS -g -O0 $innodb_extra_debug -DSAFE_MUTEX -DSAFEMALLOC" |
2342 | extra_config_51="--with-debug=full" |
- The MLOG_FILE_DELETE bits need reconcilation and/or explanation bugs.mysql. com/bug. php?id= 43948 and /bugs.launchpad .net/percona- xtrabackup/ +bug/1121072
on why the already existing hashed log rec handling in the
patches for buf_page_read_low() is not enough. Maybe it's
possible to tweak buf_page_read_low() patch instead of adding
more patches to log0recv.c? Please see
http://
https:/
which I have closed as Invalid due to this MP.
- Will the following work:
- XtraBackup creates a list of tablespaces;
- CREATE TABLE foo is issued (optionally maybe even CREATE
DATABASE first);
- XtraBackup proceeds with backup;
- Incremental backup is taken. Will it contain foo? It is
possible that some of the foo writes will be captured in the
full backup redo log backup.
I guess this question boils down to "is fil_system snapshot
taking atomic with the rest of backup state." CREATE TABLE
specifically because other scenarios seem to be covered by this
fix. I am not implying that I suspect it will or will not, I
don't know and am curious.
- This might be outside the scope of the current fix, but since
you are backporting the mysqldump backup verifier, I am
mentioning it here. If there's a bug/blueprint open for this,
please point me there: mysqldump verification probably would miss
secondary index tree corruptions, wouldn't it?
- What are the s/AM_CONFIG_ HEADER/ AC_CONFIG_ HEADERS bits for?
Some bug fixed? If yes, is there a # ref?
- Likewise for configure.cmake patch bits?
- I recall seeing utils/build.sh patch elsewhere, yet there is
only one unmerged revision in this MP. Is this intended?