Merge lp:~akopytov/percona-xtrabackup/bug1079700-2.1 into lp:percona-xtrabackup/2.1
- bug1079700-2.1
- Merge into 2.1
Status: | Merged |
---|---|
Approved by: | Laurynas Biveinis |
Approved revision: | 596 |
Merged at revision: | 602 |
Proposed branch: | lp:~akopytov/percona-xtrabackup/bug1079700-2.1 |
Merge into: | lp:percona-xtrabackup/2.1 |
Diff against target: |
1977 lines (+750/-183) 9 files modified
patches/innodb51.patch (+116/-22) patches/innodb55.patch (+105/-22) patches/innodb56.patch (+102/-26) patches/xtradb51.patch (+118/-25) patches/xtradb55.patch (+106/-23) src/fil_cur.cc (+104/-27) src/fil_cur.h (+1/-0) src/xtrabackup.cc (+61/-7) test/t/ddl.sh (+37/-31) |
To merge this branch: | bzr merge lp:~akopytov/percona-xtrabackup/bug1079700-2.1 |
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 : | # |

Laurynas Biveinis (laurynas-biveinis) : | # |
Preview Diff
1 | === modified file 'patches/innodb51.patch' |
2 | --- patches/innodb51.patch 2013-04-16 14:34:55 +0000 |
3 | +++ patches/innodb51.patch 2013-05-08 05:18:19 +0000 |
4 | @@ -474,7 +474,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 | @@ -483,7 +536,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 | @@ -492,7 +545,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 | @@ -503,7 +556,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 | @@ -516,7 +569,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 | @@ -622,7 +675,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 | @@ -631,7 +684,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 | @@ -646,7 +699,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 | @@ -655,7 +708,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 | @@ -666,7 +719,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 | @@ -740,7 +793,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 | @@ -748,6 +801,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 | @@ -961,7 +1015,35 @@ |
165 | |
166 | ib_uint64_t end_lsn; |
167 | |
168 | -@@ -2297,7 +2306,7 @@ |
169 | +@@ -1762,6 +1771,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 +1816,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 +2318,7 @@ |
198 | || type == MLOG_FILE_RENAME |
199 | || type == MLOG_FILE_DELETE) { |
200 | ut_a(space); |
201 | @@ -970,7 +1052,7 @@ |
202 | if (recv_replay_file_ops) { |
203 | |
204 | /* In ibbackup --apply-log, replay an .ibd file |
205 | -@@ -2320,7 +2329,7 @@ |
206 | +@@ -2320,7 +2341,7 @@ |
207 | ut_error; |
208 | } |
209 | } |
210 | @@ -979,7 +1061,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 +2746,11 @@ |
215 | +@@ -2737,8 +2758,11 @@ |
216 | |
217 | fprintf(stderr, |
218 | "InnoDB: Doing recovery: scanned up to" |
219 | @@ -993,7 +1075,7 @@ |
220 | } |
221 | } |
222 | |
223 | -@@ -2841,7 +2845,7 @@ |
224 | +@@ -2841,7 +2865,7 @@ |
225 | "InnoDB: Reading tablespace information" |
226 | " from the .ibd files...\n"); |
227 | |
228 | @@ -1002,7 +1084,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 +2862,14 @@ |
233 | +@@ -2850,12 +2874,14 @@ |
234 | |
235 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
236 | |
237 | @@ -1018,7 +1100,7 @@ |
238 | } |
239 | } |
240 | |
241 | -@@ -3005,6 +3019,7 @@ |
242 | +@@ -3005,6 +3031,7 @@ |
243 | recv_sys->recovered_lsn = checkpoint_lsn; |
244 | |
245 | srv_start_lsn = checkpoint_lsn; |
246 | @@ -1026,7 +1108,7 @@ |
247 | } |
248 | |
249 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
250 | -@@ -3286,6 +3301,7 @@ |
251 | +@@ -3286,6 +3313,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 | @@ -1111,17 +1193,18 @@ |
256 | |
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 | @@ -1130,7 +1213,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 | @@ -1138,7 +1221,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 | @@ -1410,3 +1493,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/innodb55.patch' |
311 | --- patches/innodb55.patch 2013-04-16 14:34:55 +0000 |
312 | +++ patches/innodb55.patch 2013-05-08 05:18:19 +0000 |
313 | @@ -464,7 +464,60 @@ |
314 | if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { |
315 | fprintf(stderr, |
316 | "InnoDB: Error: the size of single-table tablespace" |
317 | -@@ -3476,7 +3581,7 @@ |
318 | +@@ -3465,7 +3570,51 @@ |
319 | + |
320 | + fil_node_create(filepath, 0, space_id, FALSE); |
321 | + func_exit: |
322 | +- os_file_close(file); |
323 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
324 | ++ inconsistencies between the file name and the actual tablespace contents |
325 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
326 | ++ the actual copy operation. */ |
327 | ++ if (srv_backup_mode) { |
328 | ++ |
329 | ++ fil_node_t* node; |
330 | ++ fil_space_t* space; |
331 | ++ |
332 | ++ mutex_enter(&fil_system->mutex); |
333 | ++ |
334 | ++ space = fil_space_get_by_id(space_id); |
335 | ++ |
336 | ++ if (space) { |
337 | ++ node = UT_LIST_GET_LAST(space->chain); |
338 | ++ |
339 | ++ /* The handle will be closed by xtrabackup in |
340 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
341 | ++ make sure no one calls fil_node_open_file() |
342 | ++ (i.e. attempts to reopen the tablespace by name) during |
343 | ++ the backup stage. */ |
344 | ++ |
345 | ++ node->open = TRUE; |
346 | ++ node->handle = file; |
347 | ++ |
348 | ++ /* The following is copied from fil_node_open_file() to |
349 | ++ pass fil_system validity checks. We cannot use |
350 | ++ fil_node_open_file() directly, as that would re-open the |
351 | ++ file by name and create another file handle. */ |
352 | ++ |
353 | ++ fil_system->n_open++; |
354 | ++ |
355 | ++ if (space->purpose == FIL_TABLESPACE && |
356 | ++ space->id != 0) { |
357 | ++ |
358 | ++ /* Put the node to the LRU list */ |
359 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
360 | ++ } |
361 | ++ } |
362 | ++ |
363 | ++ mutex_exit(&fil_system->mutex); |
364 | ++ } else { |
365 | ++ |
366 | ++ os_file_close(file); |
367 | ++ } |
368 | + ut_free(buf2); |
369 | + mem_free(filepath); |
370 | + } |
371 | +@@ -3476,7 +3625,7 @@ |
372 | idea is to read as much good data as we can and jump over bad data. |
373 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
374 | of the directory */ |
375 | @@ -473,7 +526,7 @@ |
376 | int |
377 | fil_file_readdir_next_file( |
378 | /*=======================*/ |
379 | -@@ -3520,7 +3625,7 @@ |
380 | +@@ -3520,7 +3669,7 @@ |
381 | @return DB_SUCCESS or error number */ |
382 | UNIV_INTERN |
383 | ulint |
384 | @@ -482,7 +535,7 @@ |
385 | /*===================================*/ |
386 | { |
387 | int ret; |
388 | -@@ -3576,7 +3681,9 @@ |
389 | +@@ -3576,7 +3725,9 @@ |
390 | dbinfo.name); |
391 | srv_normalize_path_for_win(dbpath); |
392 | |
393 | @@ -493,7 +546,7 @@ |
394 | |
395 | if (dbdir != NULL) { |
396 | /* printf("Opened dir %s\n", dbinfo.name); */ |
397 | -@@ -3602,8 +3709,11 @@ |
398 | +@@ -3602,8 +3753,11 @@ |
399 | ".ibd")) { |
400 | /* The name ends in .ibd; try opening |
401 | the file */ |
402 | @@ -506,7 +559,7 @@ |
403 | } |
404 | next_file_item: |
405 | ret = fil_file_readdir_next_file(&err, |
406 | -@@ -3775,15 +3885,97 @@ |
407 | +@@ -3775,15 +3929,97 @@ |
408 | "InnoDB: in InnoDB data dictionary" |
409 | " has tablespace id %lu,\n" |
410 | "InnoDB: but tablespace with that id" |
411 | @@ -612,7 +665,7 @@ |
412 | } else { |
413 | ut_print_timestamp(stderr); |
414 | fputs(" InnoDB: Error: table ", stderr); |
415 | -@@ -4172,7 +4364,7 @@ |
416 | +@@ -4172,7 +4408,7 @@ |
417 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
418 | mutex. */ |
419 | static |
420 | @@ -621,7 +674,7 @@ |
421 | fil_node_prepare_for_io( |
422 | /*====================*/ |
423 | fil_node_t* node, /*!< in: file node */ |
424 | -@@ -4192,10 +4384,13 @@ |
425 | +@@ -4192,10 +4428,13 @@ |
426 | } |
427 | |
428 | if (node->open == FALSE) { |
429 | @@ -636,7 +689,7 @@ |
430 | } |
431 | |
432 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
433 | -@@ -4208,6 +4403,8 @@ |
434 | +@@ -4208,6 +4447,8 @@ |
435 | } |
436 | |
437 | node->n_pending++; |
438 | @@ -645,7 +698,7 @@ |
439 | } |
440 | |
441 | /********************************************************************//** |
442 | -@@ -4390,6 +4587,16 @@ |
443 | +@@ -4390,6 +4631,16 @@ |
444 | |
445 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
446 | |
447 | @@ -697,7 +750,7 @@ |
448 | Returns TRUE if a single-table tablespace does not exist in the memory cache, |
449 | --- a/storage/innobase/include/srv0srv.h |
450 | +++ b/storage/innobase/include/srv0srv.h |
451 | -@@ -218,6 +218,10 @@ |
452 | +@@ -218,6 +218,11 @@ |
453 | extern ulong srv_max_purge_lag; |
454 | |
455 | extern ulong srv_replication_delay; |
456 | @@ -705,6 +758,7 @@ |
457 | +extern ibool srv_read_only; |
458 | +extern ibool srv_fake_write; |
459 | +extern ibool srv_apply_log_only; |
460 | ++extern ibool srv_backup_mode; |
461 | /*-------------------------------------------*/ |
462 | |
463 | extern ulint srv_n_rows_inserted; |
464 | @@ -874,7 +928,35 @@ |
465 | |
466 | ib_uint64_t end_lsn; |
467 | |
468 | -@@ -2308,7 +2317,7 @@ |
469 | +@@ -1774,6 +1783,18 @@ |
470 | + ulint zip_size = fil_space_get_zip_size(space); |
471 | + ulint page_no = recv_addr->page_no; |
472 | + |
473 | ++ /* By now we have replayed all DDL log records from the |
474 | ++ current batch. Check if the space ID is still valid in |
475 | ++ the entry being processed, and ignore it if it is not.*/ |
476 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
477 | ++ |
478 | ++ ut_a(recv_sys->n_addrs); |
479 | ++ |
480 | ++ recv_addr->state = RECV_PROCESSED; |
481 | ++ recv_sys->n_addrs--; |
482 | ++ |
483 | ++ goto next; |
484 | ++ } |
485 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
486 | + if (!has_printed) { |
487 | + ut_print_timestamp(stderr); |
488 | +@@ -1807,7 +1828,7 @@ |
489 | + |
490 | + mutex_enter(&(recv_sys->mutex)); |
491 | + } |
492 | +- |
493 | ++next: |
494 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
495 | + } |
496 | + |
497 | +@@ -2308,7 +2329,7 @@ |
498 | || type == MLOG_FILE_RENAME |
499 | || type == MLOG_FILE_DELETE) { |
500 | ut_a(space); |
501 | @@ -883,7 +965,7 @@ |
502 | if (recv_replay_file_ops) { |
503 | |
504 | /* In ibbackup --apply-log, replay an .ibd file |
505 | -@@ -2331,7 +2340,7 @@ |
506 | +@@ -2331,7 +2352,7 @@ |
507 | ut_error; |
508 | } |
509 | } |
510 | @@ -892,7 +974,7 @@ |
511 | /* In normal mysqld crash recovery we do not try to |
512 | replay file operations */ |
513 | #ifdef UNIV_LOG_LSN_DEBUG |
514 | -@@ -2748,8 +2757,11 @@ |
515 | +@@ -2748,8 +2769,11 @@ |
516 | |
517 | fprintf(stderr, |
518 | "InnoDB: Doing recovery: scanned up to" |
519 | @@ -906,7 +988,7 @@ |
520 | } |
521 | } |
522 | |
523 | -@@ -2854,7 +2858,7 @@ |
524 | +@@ -2854,7 +2878,7 @@ |
525 | "InnoDB: Reading tablespace information" |
526 | " from the .ibd files...\n"); |
527 | |
528 | @@ -915,7 +997,7 @@ |
529 | |
530 | /* If we are using the doublewrite method, we will |
531 | check if there are half-written pages in data files, |
532 | -@@ -2863,12 +2875,14 @@ |
533 | +@@ -2863,12 +2887,14 @@ |
534 | |
535 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
536 | |
537 | @@ -931,7 +1013,7 @@ |
538 | } |
539 | } |
540 | |
541 | -@@ -3018,6 +3032,7 @@ |
542 | +@@ -3018,6 +3044,7 @@ |
543 | recv_sys->recovered_lsn = checkpoint_lsn; |
544 | |
545 | srv_start_lsn = checkpoint_lsn; |
546 | @@ -939,7 +1021,7 @@ |
547 | } |
548 | |
549 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
550 | -@@ -3299,6 +3314,7 @@ |
551 | +@@ -3299,6 +3326,7 @@ |
552 | that the data dictionary tables will be free of any locks. |
553 | The data dictionary latch should guarantee that there is at |
554 | most one data dictionary transaction active at a time. */ |
555 | @@ -1023,17 +1105,18 @@ |
556 | } |
557 | --- a/storage/innobase/srv/srv0srv.c |
558 | +++ b/storage/innobase/srv/srv0srv.c |
559 | -@@ -399,6 +399,9 @@ |
560 | +@@ -399,6 +399,10 @@ |
561 | |
562 | UNIV_INTERN ulong srv_replication_delay = 0; |
563 | |
564 | +UNIV_INTERN ibool srv_read_only = FALSE; |
565 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
566 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
567 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
568 | /*-------------------------------------------*/ |
569 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
570 | UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; |
571 | -@@ -1078,7 +1081,7 @@ |
572 | +@@ -1078,7 +1082,7 @@ |
573 | } |
574 | |
575 | /* Initialize some INFORMATION SCHEMA internal structures */ |
576 | @@ -1042,7 +1125,7 @@ |
577 | } |
578 | |
579 | /*********************************************************************//** |
580 | -@@ -1089,6 +1092,7 @@ |
581 | +@@ -1089,6 +1093,7 @@ |
582 | /*==========*/ |
583 | { |
584 | os_fast_mutex_free(&srv_conc_mutex); |
585 | @@ -1050,7 +1133,7 @@ |
586 | mem_free(srv_conc_slots); |
587 | srv_conc_slots = NULL; |
588 | |
589 | -@@ -1102,6 +1106,7 @@ |
590 | +@@ -1102,6 +1107,7 @@ |
591 | srv_mysql_table = NULL; |
592 | |
593 | trx_i_s_cache_free(trx_i_s_cache); |
594 | @@ -1058,7 +1141,7 @@ |
595 | } |
596 | |
597 | /*********************************************************************//** |
598 | -@@ -1717,7 +1722,7 @@ |
599 | +@@ -1717,7 +1723,7 @@ |
600 | } |
601 | |
602 | /* Record the lock wait time for this thread */ |
603 | |
604 | === modified file 'patches/innodb56.patch' |
605 | --- patches/innodb56.patch 2013-05-04 05:26:19 +0000 |
606 | +++ patches/innodb56.patch 2013-05-08 05:18:19 +0000 |
607 | @@ -375,7 +375,7 @@ |
608 | |
609 | + /* Ignore .isl files on XtraBackup recovery. All tablespaces must be |
610 | + local. */ |
611 | -+ if (!recv_recovery_on) { |
612 | ++ if (srv_backup_mode) { |
613 | /* Check for a link file which locates a remote tablespace. */ |
614 | remote.success = fil_open_linked_file( |
615 | tablename, &remote.filepath, &remote.file); |
616 | @@ -396,7 +396,60 @@ |
617 | ib_logf(IB_LOG_LEVEL_ERROR, |
618 | "The size of single-table tablespace file %s " |
619 | "is only " UINT64PF ", should be at least %lu!", |
620 | -@@ -4263,7 +4390,7 @@ |
621 | +@@ -4243,7 +4370,51 @@ |
622 | + } |
623 | + |
624 | + func_exit: |
625 | +- os_file_close(fsp->file); |
626 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
627 | ++ inconsistencies between the file name and the actual tablespace contents |
628 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
629 | ++ the actual copy operation. */ |
630 | ++ if (srv_backup_mode) { |
631 | ++ |
632 | ++ fil_node_t* node; |
633 | ++ fil_space_t* space; |
634 | ++ |
635 | ++ mutex_enter(&fil_system->mutex); |
636 | ++ |
637 | ++ space = fil_space_get_by_id(fsp->id); |
638 | ++ |
639 | ++ if (space) { |
640 | ++ node = UT_LIST_GET_LAST(space->chain); |
641 | ++ |
642 | ++ /* The handle will be closed by xtrabackup in |
643 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
644 | ++ make sure no one calls fil_node_open_file() |
645 | ++ (i.e. attempts to reopen the tablespace by name) during |
646 | ++ the backup stage. */ |
647 | ++ |
648 | ++ node->open = TRUE; |
649 | ++ node->handle = fsp->file; |
650 | ++ |
651 | ++ /* The following is copied from fil_node_open_file() to |
652 | ++ pass fil_system validaty checks. We cannot use |
653 | ++ fil_node_open_file() directly, as that would re-open the |
654 | ++ file by name and create another file handle. */ |
655 | ++ |
656 | ++ fil_system->n_open++; |
657 | ++ fil_n_file_opened++; |
658 | ++ |
659 | ++ if (fil_space_belongs_in_lru(space)) { |
660 | ++ |
661 | ++ /* Put the node to the LRU list */ |
662 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
663 | ++ } |
664 | ++ } |
665 | ++ |
666 | ++ mutex_exit(&fil_system->mutex); |
667 | ++ } else { |
668 | ++ |
669 | ++ os_file_close(fsp->file); |
670 | ++ } |
671 | + |
672 | + #ifdef UNIV_HOTBACKUP |
673 | + func_exit_after_close: |
674 | +@@ -4263,7 +4434,7 @@ |
675 | idea is to read as much good data as we can and jump over bad data. |
676 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
677 | of the directory */ |
678 | @@ -405,7 +458,7 @@ |
679 | int |
680 | fil_file_readdir_next_file( |
681 | /*=======================*/ |
682 | -@@ -4303,7 +4430,7 @@ |
683 | +@@ -4303,7 +4474,7 @@ |
684 | @return DB_SUCCESS or error number */ |
685 | UNIV_INTERN |
686 | dberr_t |
687 | @@ -414,7 +467,7 @@ |
688 | /*===================================*/ |
689 | { |
690 | int ret; |
691 | -@@ -4359,7 +4486,9 @@ |
692 | +@@ -4359,7 +4530,9 @@ |
693 | "%s/%s", fil_path_to_mysql_datadir, dbinfo.name); |
694 | srv_normalize_path_for_win(dbpath); |
695 | |
696 | @@ -425,7 +478,7 @@ |
697 | |
698 | if (dbdir != NULL) { |
699 | |
700 | -@@ -4380,9 +4509,15 @@ |
701 | +@@ -4380,9 +4553,15 @@ |
702 | && (0 == strcmp(fileinfo.name |
703 | + strlen(fileinfo.name) - 4, |
704 | ".ibd") |
705 | @@ -433,7 +486,7 @@ |
706 | + /* Ignore .isl files on XtraBackup |
707 | + recovery, all tablespaces must be |
708 | + local. */ |
709 | -+ || (!recv_recovery_on && |
710 | ++ || (srv_backup_mode && |
711 | + 0 == strcmp(fileinfo.name |
712 | + strlen(fileinfo.name) - 4, |
713 | - ".isl"))) { |
714 | @@ -443,7 +496,7 @@ |
715 | /* The name ends in .ibd or .isl; |
716 | try opening the file */ |
717 | fil_load_single_table_tablespace( |
718 | -@@ -4538,6 +4673,7 @@ |
719 | +@@ -4538,6 +4717,7 @@ |
720 | { |
721 | fil_space_t* fnamespace; |
722 | fil_space_t* space; |
723 | @@ -451,7 +504,7 @@ |
724 | |
725 | ut_ad(fil_system); |
726 | |
727 | -@@ -4615,6 +4751,10 @@ |
728 | +@@ -4615,6 +4795,10 @@ |
729 | if (fnamespace == NULL) { |
730 | if (print_error_if_does_not_exist) { |
731 | fil_report_missing_tablespace(name, id); |
732 | @@ -462,7 +515,7 @@ |
733 | } |
734 | } else { |
735 | ut_print_timestamp(stderr); |
736 | -@@ -4638,6 +4778,10 @@ |
737 | +@@ -4638,6 +4822,10 @@ |
738 | |
739 | mutex_exit(&fil_system->mutex); |
740 | |
741 | @@ -473,7 +526,7 @@ |
742 | return(FALSE); |
743 | } |
744 | |
745 | -@@ -4728,6 +4872,7 @@ |
746 | +@@ -4728,6 +4916,7 @@ |
747 | ulint page_size; |
748 | ulint pages_added; |
749 | ibool success; |
750 | @@ -481,7 +534,7 @@ |
751 | |
752 | ut_ad(!srv_read_only_mode); |
753 | |
754 | -@@ -4772,13 +4917,17 @@ |
755 | +@@ -4772,13 +4961,17 @@ |
756 | goto retry; |
757 | } |
758 | |
759 | @@ -500,7 +553,7 @@ |
760 | start_page_no = space->size; |
761 | file_start_page_no = space->size - node->size; |
762 | |
763 | -@@ -5024,7 +5173,7 @@ |
764 | +@@ -5024,7 +5217,7 @@ |
765 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
766 | mutex. */ |
767 | static |
768 | @@ -509,7 +562,7 @@ |
769 | fil_node_prepare_for_io( |
770 | /*====================*/ |
771 | fil_node_t* node, /*!< in: file node */ |
772 | -@@ -5044,9 +5193,12 @@ |
773 | +@@ -5044,9 +5237,12 @@ |
774 | } |
775 | |
776 | if (node->open == FALSE) { |
777 | @@ -523,7 +576,7 @@ |
778 | } |
779 | |
780 | if (node->n_pending == 0 && fil_space_belongs_in_lru(space)) { |
781 | -@@ -5058,6 +5210,8 @@ |
782 | +@@ -5058,6 +5254,8 @@ |
783 | } |
784 | |
785 | node->n_pending++; |
786 | @@ -532,7 +585,7 @@ |
787 | } |
788 | |
789 | /********************************************************************//** |
790 | -@@ -5259,6 +5413,16 @@ |
791 | +@@ -5259,6 +5457,16 @@ |
792 | |
793 | ut_ad(mode != OS_AIO_IBUF || space->purpose == FIL_TABLESPACE); |
794 | |
795 | @@ -549,7 +602,7 @@ |
796 | node = UT_LIST_GET_FIRST(space->chain); |
797 | |
798 | for (;;) { |
799 | -@@ -5290,7 +5454,11 @@ |
800 | +@@ -5290,7 +5498,11 @@ |
801 | } |
802 | |
803 | /* Open file if closed */ |
804 | @@ -562,7 +615,7 @@ |
805 | |
806 | /* Check that at least the start offset is within the bounds of a |
807 | single-table tablespace, including rollback tablespaces. */ |
808 | -@@ -6164,6 +6332,7 @@ |
809 | +@@ -6164,6 +6376,7 @@ |
810 | return(err); |
811 | } |
812 | |
813 | @@ -570,7 +623,7 @@ |
814 | /****************************************************************//** |
815 | Generate redo logs for swapping two .ibd files */ |
816 | UNIV_INTERN |
817 | -@@ -6187,4 +6356,4 @@ |
818 | +@@ -6187,4 +6400,4 @@ |
819 | 0, 0, new_name, old_name, &mtr); |
820 | mtr_commit(&mtr); |
821 | } |
822 | @@ -713,13 +766,15 @@ |
823 | Returns TRUE if a single-table tablespace does not exist in the memory cache, |
824 | --- a/storage/innobase/include/srv0srv.h |
825 | +++ b/storage/innobase/include/srv0srv.h |
826 | -@@ -353,6 +353,9 @@ |
827 | +@@ -353,6 +353,11 @@ |
828 | extern ulong srv_max_purge_lag_delay; |
829 | |
830 | extern ulong srv_replication_delay; |
831 | + |
832 | +extern ibool srv_apply_log_only; |
833 | + |
834 | ++extern ibool srv_backup_mode; |
835 | ++ |
836 | /*-------------------------------------------*/ |
837 | |
838 | extern ibool srv_print_innodb_monitor; |
839 | @@ -814,7 +869,26 @@ |
840 | |
841 | lsn_t end_lsn; |
842 | |
843 | -@@ -2413,7 +2424,7 @@ |
844 | +@@ -1868,6 +1879,18 @@ |
845 | + ulint zip_size = fil_space_get_zip_size(space); |
846 | + ulint page_no = recv_addr->page_no; |
847 | + |
848 | ++ /* By now we have replayed all DDL log records from the |
849 | ++ current batch. Check if the space ID is still valid in |
850 | ++ the entry being processed, and ignore it if it is not.*/ |
851 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
852 | ++ |
853 | ++ ut_a(recv_sys->n_addrs); |
854 | ++ |
855 | ++ recv_addr->state = RECV_PROCESSED; |
856 | ++ recv_sys->n_addrs--; |
857 | ++ |
858 | ++ continue; |
859 | ++ } |
860 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
861 | + if (!has_printed) { |
862 | + ib_logf(IB_LOG_LEVEL_INFO, |
863 | +@@ -2413,7 +2436,7 @@ |
864 | || type == MLOG_FILE_RENAME |
865 | || type == MLOG_FILE_DELETE) { |
866 | ut_a(space); |
867 | @@ -823,7 +897,7 @@ |
868 | if (recv_replay_file_ops) { |
869 | |
870 | /* In ibbackup --apply-log, replay an .ibd file |
871 | -@@ -2436,7 +2447,7 @@ |
872 | +@@ -2436,7 +2459,7 @@ |
873 | ut_error; |
874 | } |
875 | } |
876 | @@ -832,7 +906,7 @@ |
877 | /* In normal mysqld crash recovery we do not try to |
878 | replay file operations */ |
879 | #ifdef UNIV_LOG_LSN_DEBUG |
880 | -@@ -2863,8 +2874,14 @@ |
881 | +@@ -2863,8 +2886,14 @@ |
882 | |
883 | fprintf(stderr, |
884 | "InnoDB: Doing recovery: scanned up to" |
885 | @@ -849,7 +923,7 @@ |
886 | } |
887 | } |
888 | |
889 | -@@ -2964,7 +2981,7 @@ |
890 | +@@ -2964,7 +2993,7 @@ |
891 | ib_logf(IB_LOG_LEVEL_INFO, |
892 | "Reading tablespace information from the .ibd files..."); |
893 | |
894 | @@ -858,7 +932,7 @@ |
895 | |
896 | /* If we are using the doublewrite method, we will |
897 | check if there are half-written pages in data files, |
898 | -@@ -3456,7 +3473,8 @@ |
899 | +@@ -3456,7 +3485,8 @@ |
900 | that the data dictionary tables will be free of any locks. |
901 | The data dictionary latch should guarantee that there is at |
902 | most one data dictionary transaction active at a time. */ |
903 | @@ -895,16 +969,18 @@ |
904 | tested with following crash point */ |
905 | --- a/storage/innobase/srv/srv0srv.cc |
906 | +++ b/storage/innobase/srv/srv0srv.cc |
907 | -@@ -349,6 +349,8 @@ |
908 | +@@ -349,6 +349,10 @@ |
909 | |
910 | UNIV_INTERN ulong srv_replication_delay = 0; |
911 | |
912 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
913 | + |
914 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
915 | ++ |
916 | /*-------------------------------------------*/ |
917 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
918 | UNIV_INTERN ulong srv_spin_wait_delay = 6; |
919 | -@@ -1808,7 +1810,8 @@ |
920 | +@@ -1808,7 +1812,8 @@ |
921 | if (ret == SRV_NONE |
922 | && srv_shutdown_state != SRV_SHUTDOWN_NONE |
923 | && trx_purge_state() != PURGE_STATE_DISABLED |
924 | |
925 | === modified file 'patches/xtradb51.patch' |
926 | --- patches/xtradb51.patch 2013-04-16 14:34:55 +0000 |
927 | +++ patches/xtradb51.patch 2013-05-08 05:18:19 +0000 |
928 | @@ -357,7 +357,60 @@ |
929 | if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { |
930 | fprintf(stderr, |
931 | "InnoDB: Error: the size of single-table tablespace" |
932 | -@@ -4247,7 +4349,7 @@ |
933 | +@@ -4236,7 +4338,51 @@ |
934 | + |
935 | + fil_node_create(filepath, 0, space_id, FALSE); |
936 | + func_exit: |
937 | +- os_file_close(file); |
938 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
939 | ++ inconsistencies between the file name and the actual tablespace contents |
940 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
941 | ++ the actual copy operation. */ |
942 | ++ if (srv_backup_mode) { |
943 | ++ |
944 | ++ fil_node_t* node; |
945 | ++ fil_space_t* space; |
946 | ++ |
947 | ++ mutex_enter(&fil_system->mutex); |
948 | ++ |
949 | ++ space = fil_space_get_by_id(space_id); |
950 | ++ |
951 | ++ if (space) { |
952 | ++ node = UT_LIST_GET_LAST(space->chain); |
953 | ++ |
954 | ++ /* The handle will be closed by xtrabackup in |
955 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
956 | ++ make sure no one calls fil_node_open_file() |
957 | ++ (i.e. attempts to reopen the tablespace by name) during |
958 | ++ the backup stage. */ |
959 | ++ |
960 | ++ node->open = TRUE; |
961 | ++ node->handle = file; |
962 | ++ |
963 | ++ /* The following is copied from fil_node_open_file() to |
964 | ++ pass fil_system validity checks. We cannot use |
965 | ++ fil_node_open_file() directly, as that would re-open the |
966 | ++ file by name and create another file handle. */ |
967 | ++ |
968 | ++ fil_system->n_open++; |
969 | ++ |
970 | ++ if (space->purpose == FIL_TABLESPACE && |
971 | ++ space->id != 0) { |
972 | ++ |
973 | ++ /* Put the node to the LRU list */ |
974 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
975 | ++ } |
976 | ++ } |
977 | ++ |
978 | ++ mutex_exit(&fil_system->mutex); |
979 | ++ } else { |
980 | ++ |
981 | ++ os_file_close(file); |
982 | ++ } |
983 | + ut_free(buf2); |
984 | + mem_free(filepath); |
985 | + } |
986 | +@@ -4247,7 +4393,7 @@ |
987 | idea is to read as much good data as we can and jump over bad data. |
988 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
989 | of the directory */ |
990 | @@ -366,7 +419,7 @@ |
991 | int |
992 | fil_file_readdir_next_file( |
993 | /*=======================*/ |
994 | -@@ -4291,7 +4393,7 @@ |
995 | +@@ -4291,7 +4437,7 @@ |
996 | @return DB_SUCCESS or error number */ |
997 | UNIV_INTERN |
998 | ulint |
999 | @@ -375,7 +428,7 @@ |
1000 | /*===================================*/ |
1001 | { |
1002 | int ret; |
1003 | -@@ -4347,7 +4449,9 @@ |
1004 | +@@ -4347,7 +4493,9 @@ |
1005 | dbinfo.name); |
1006 | srv_normalize_path_for_win(dbpath); |
1007 | |
1008 | @@ -386,7 +439,7 @@ |
1009 | |
1010 | if (dbdir != NULL) { |
1011 | /* printf("Opened dir %s\n", dbinfo.name); */ |
1012 | -@@ -4373,8 +4477,11 @@ |
1013 | +@@ -4373,8 +4521,11 @@ |
1014 | ".ibd")) { |
1015 | /* The name ends in .ibd; try opening |
1016 | the file */ |
1017 | @@ -399,7 +452,7 @@ |
1018 | } |
1019 | next_file_item: |
1020 | ret = fil_file_readdir_next_file(&err, |
1021 | -@@ -4546,15 +4653,97 @@ |
1022 | +@@ -4546,15 +4697,97 @@ |
1023 | "InnoDB: in InnoDB data dictionary" |
1024 | " has tablespace id %lu,\n" |
1025 | "InnoDB: but tablespace with that id" |
1026 | @@ -505,7 +558,7 @@ |
1027 | } else { |
1028 | ut_print_timestamp(stderr); |
1029 | fputs(" InnoDB: Error: table ", stderr); |
1030 | -@@ -4953,7 +5142,7 @@ |
1031 | +@@ -4953,7 +5186,7 @@ |
1032 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
1033 | mutex. */ |
1034 | static |
1035 | @@ -514,7 +567,7 @@ |
1036 | fil_node_prepare_for_io( |
1037 | /*====================*/ |
1038 | fil_node_t* node, /*!< in: file node */ |
1039 | -@@ -4973,10 +5162,13 @@ |
1040 | +@@ -4973,10 +5206,13 @@ |
1041 | } |
1042 | |
1043 | if (node->open == FALSE) { |
1044 | @@ -529,7 +582,7 @@ |
1045 | } |
1046 | |
1047 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
1048 | -@@ -4989,6 +5181,8 @@ |
1049 | +@@ -4989,6 +5225,8 @@ |
1050 | } |
1051 | |
1052 | node->n_pending++; |
1053 | @@ -538,7 +591,7 @@ |
1054 | } |
1055 | |
1056 | /********************************************************************//** |
1057 | -@@ -5125,7 +5319,9 @@ |
1058 | +@@ -5125,7 +5363,9 @@ |
1059 | ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE) |
1060 | || !ibuf_bitmap_page(zip_size, block_offset) |
1061 | || sync || is_log); |
1062 | @@ -549,7 +602,7 @@ |
1063 | || ibuf_page(space_id, zip_size, block_offset, NULL)); |
1064 | # endif /* UNIV_LOG_DEBUG */ |
1065 | if (sync) { |
1066 | -@@ -5190,6 +5386,16 @@ |
1067 | +@@ -5190,6 +5430,16 @@ |
1068 | |
1069 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
1070 | |
1071 | @@ -681,13 +734,14 @@ |
1072 | return(buf); |
1073 | --- a/storage/innodb_plugin/include/srv0srv.h |
1074 | +++ b/storage/innodb_plugin/include/srv0srv.h |
1075 | -@@ -226,6 +226,10 @@ |
1076 | +@@ -226,6 +226,11 @@ |
1077 | |
1078 | extern ulong srv_replication_delay; |
1079 | |
1080 | +extern ibool srv_read_only; |
1081 | +extern ibool srv_fake_write; |
1082 | +extern ibool srv_apply_log_only; |
1083 | ++extern ibool srv_backup_mode; |
1084 | + |
1085 | extern long long srv_ibuf_max_size; |
1086 | extern ulint srv_ibuf_active_contract; |
1087 | @@ -876,7 +930,35 @@ |
1088 | |
1089 | ib_uint64_t end_lsn; |
1090 | |
1091 | -@@ -2369,7 +2377,7 @@ |
1092 | +@@ -1830,6 +1838,18 @@ |
1093 | + ulint zip_size = fil_space_get_zip_size(space); |
1094 | + ulint page_no = recv_addr->page_no; |
1095 | + |
1096 | ++ /* By now we have replayed all DDL log records from the |
1097 | ++ current batch. Check if the space ID is still valid in |
1098 | ++ the entry being processed, and ignore it if it is not.*/ |
1099 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
1100 | ++ |
1101 | ++ ut_a(recv_sys->n_addrs); |
1102 | ++ |
1103 | ++ recv_addr->state = RECV_PROCESSED; |
1104 | ++ recv_sys->n_addrs--; |
1105 | ++ |
1106 | ++ goto next; |
1107 | ++ } |
1108 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
1109 | + if (!has_printed) { |
1110 | + ut_print_timestamp(stderr); |
1111 | +@@ -1863,7 +1883,7 @@ |
1112 | + |
1113 | + mutex_enter(&(recv_sys->mutex)); |
1114 | + } |
1115 | +- |
1116 | ++next: |
1117 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
1118 | + } |
1119 | + |
1120 | +@@ -2369,7 +2389,7 @@ |
1121 | || type == MLOG_FILE_RENAME |
1122 | || type == MLOG_FILE_DELETE) { |
1123 | ut_a(space); |
1124 | @@ -885,7 +967,7 @@ |
1125 | if (recv_replay_file_ops) { |
1126 | |
1127 | /* In ibbackup --apply-log, replay an .ibd file |
1128 | -@@ -2392,7 +2400,7 @@ |
1129 | +@@ -2392,7 +2412,7 @@ |
1130 | ut_error; |
1131 | } |
1132 | } |
1133 | @@ -894,7 +976,7 @@ |
1134 | /* In normal mysqld crash recovery we do not try to |
1135 | replay file operations */ |
1136 | #ifdef UNIV_LOG_LSN_DEBUG |
1137 | -@@ -2809,8 +2817,11 @@ |
1138 | +@@ -2809,8 +2829,11 @@ |
1139 | |
1140 | fprintf(stderr, |
1141 | "InnoDB: Doing recovery: scanned up to" |
1142 | @@ -908,7 +990,7 @@ |
1143 | } |
1144 | } |
1145 | |
1146 | -@@ -2913,7 +2916,7 @@ |
1147 | +@@ -2913,7 +2936,7 @@ |
1148 | "InnoDB: Reading tablespace information" |
1149 | " from the .ibd files...\n"); |
1150 | |
1151 | @@ -917,7 +999,7 @@ |
1152 | |
1153 | /* If we are using the doublewrite method, we will |
1154 | check if there are half-written pages in data files, |
1155 | -@@ -2922,12 +2933,14 @@ |
1156 | +@@ -2922,12 +2945,14 @@ |
1157 | |
1158 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
1159 | |
1160 | @@ -933,7 +1015,7 @@ |
1161 | } |
1162 | } |
1163 | |
1164 | -@@ -3095,6 +3108,7 @@ |
1165 | +@@ -3095,6 +3120,7 @@ |
1166 | recv_sys->recovered_lsn = checkpoint_lsn; |
1167 | |
1168 | srv_start_lsn = checkpoint_lsn; |
1169 | @@ -941,7 +1023,7 @@ |
1170 | } |
1171 | |
1172 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
1173 | -@@ -3453,6 +3467,7 @@ |
1174 | +@@ -3453,6 +3479,7 @@ |
1175 | that the data dictionary tables will be free of any locks. |
1176 | The data dictionary latch should guarantee that there is at |
1177 | most one data dictionary transaction active at a time. */ |
1178 | @@ -1038,18 +1120,19 @@ |
1179 | /* prototypes for new functions added to ha_innodb.cc */ |
1180 | ibool innobase_get_slow_log(); |
1181 | |
1182 | -@@ -415,6 +410,10 @@ |
1183 | +@@ -415,6 +410,11 @@ |
1184 | |
1185 | UNIV_INTERN ulong srv_replication_delay = 0; |
1186 | |
1187 | +UNIV_INTERN ibool srv_read_only = FALSE; |
1188 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
1189 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
1190 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
1191 | + |
1192 | UNIV_INTERN long long srv_ibuf_max_size = 0; |
1193 | UNIV_INTERN ulint srv_ibuf_active_contract = 0; /* 0:disable 1:enable */ |
1194 | UNIV_INTERN ulint srv_ibuf_accel_rate = 100; |
1195 | -@@ -1065,7 +1064,7 @@ |
1196 | +@@ -1065,7 +1065,7 @@ |
1197 | } |
1198 | |
1199 | /* Initialize some INFORMATION SCHEMA internal structures */ |
1200 | @@ -1058,7 +1141,7 @@ |
1201 | } |
1202 | |
1203 | /*********************************************************************//** |
1204 | -@@ -1076,6 +1075,7 @@ |
1205 | +@@ -1076,6 +1076,7 @@ |
1206 | /*==========*/ |
1207 | { |
1208 | os_fast_mutex_free(&srv_conc_mutex); |
1209 | @@ -1066,7 +1149,7 @@ |
1210 | mem_free(srv_conc_slots); |
1211 | srv_conc_slots = NULL; |
1212 | |
1213 | -@@ -1089,6 +1089,7 @@ |
1214 | +@@ -1089,6 +1090,7 @@ |
1215 | srv_mysql_table = NULL; |
1216 | |
1217 | trx_i_s_cache_free(trx_i_s_cache); |
1218 | @@ -1074,7 +1157,7 @@ |
1219 | } |
1220 | |
1221 | /*********************************************************************//** |
1222 | -@@ -2570,36 +2571,6 @@ |
1223 | +@@ -2570,36 +2572,6 @@ |
1224 | old_sema = sema; |
1225 | } |
1226 | |
1227 | @@ -1163,7 +1246,6 @@ |
1228 | |
1229 | if (srv_auto_extend_last_data_file |
1230 | && sum_of_data_file_sizes < tablespace_size_in_header) { |
1231 | -- |
1232 | + /* extend table space size aligning with header */ |
1233 | + ulint actual_size; |
1234 | + fil_extend_space_to_desired_size(&actual_size, 0, tablespace_size_in_header); |
1235 | @@ -1174,7 +1256,7 @@ |
1236 | + (ulong) actual_size, |
1237 | + (ulong) tablespace_size_in_header); |
1238 | + } |
1239 | -+ |
1240 | + |
1241 | +#ifdef UNDEFINED |
1242 | fprintf(stderr, |
1243 | "InnoDB: Error: tablespace size stored in header" |
1244 | @@ -1497,3 +1579,14 @@ |
1245 | |
1246 | UNIV_MEM_FREE(buf, n); |
1247 | } |
1248 | +--- a/configure.in |
1249 | ++++ b/configure.in |
1250 | +@@ -22,7 +22,7 @@ |
1251 | + AM_INIT_AUTOMAKE([1.9 tar-ustar]) |
1252 | + AC_PROG_LIBTOOL |
1253 | + |
1254 | +-AM_CONFIG_HEADER([include/config.h]) |
1255 | ++AC_CONFIG_HEADERS([include/config.h]) |
1256 | + |
1257 | + # Request support for automake silent-rules if available. |
1258 | + # Default to verbose output. One can use the configure-time |
1259 | |
1260 | === modified file 'patches/xtradb55.patch' |
1261 | --- patches/xtradb55.patch 2013-04-16 14:34:55 +0000 |
1262 | +++ patches/xtradb55.patch 2013-05-08 05:18:19 +0000 |
1263 | @@ -356,7 +356,60 @@ |
1264 | if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { |
1265 | fprintf(stderr, |
1266 | "InnoDB: Error: the size of single-table tablespace" |
1267 | -@@ -4299,7 +4402,7 @@ |
1268 | +@@ -4288,7 +4391,51 @@ |
1269 | + |
1270 | + fil_node_create(filepath, 0, space_id, FALSE); |
1271 | + func_exit: |
1272 | +- os_file_close(file); |
1273 | ++ /* We reuse file handles on the backup stage in XtraBackup to avoid |
1274 | ++ inconsistencies between the file name and the actual tablespace contents |
1275 | ++ if a DDL occurs between a fil_load_single_table_tablespaces() call and |
1276 | ++ the actual copy operation. */ |
1277 | ++ if (srv_backup_mode) { |
1278 | ++ |
1279 | ++ fil_node_t* node; |
1280 | ++ fil_space_t* space; |
1281 | ++ |
1282 | ++ mutex_enter(&fil_system->mutex); |
1283 | ++ |
1284 | ++ space = fil_space_get_by_id(space_id); |
1285 | ++ |
1286 | ++ if (space) { |
1287 | ++ node = UT_LIST_GET_LAST(space->chain); |
1288 | ++ |
1289 | ++ /* The handle will be closed by xtrabackup in |
1290 | ++ xtrabackup_copy_datafile(). We set node->open to TRUE to |
1291 | ++ make sure no one calls fil_node_open_file() |
1292 | ++ (i.e. attempts to reopen the tablespace by name) during |
1293 | ++ the backup stage. */ |
1294 | ++ |
1295 | ++ node->open = TRUE; |
1296 | ++ node->handle = file; |
1297 | ++ |
1298 | ++ /* The following is copied from fil_node_open_file() to |
1299 | ++ pass fil_system validity checks. We cannot use |
1300 | ++ fil_node_open_file() directly, as that would re-open the |
1301 | ++ file by name and create another file handle. */ |
1302 | ++ |
1303 | ++ fil_system->n_open++; |
1304 | ++ |
1305 | ++ if (space->purpose == FIL_TABLESPACE && |
1306 | ++ space->id != 0) { |
1307 | ++ |
1308 | ++ /* Put the node to the LRU list */ |
1309 | ++ UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
1310 | ++ } |
1311 | ++ } |
1312 | ++ |
1313 | ++ mutex_exit(&fil_system->mutex); |
1314 | ++ } else { |
1315 | ++ |
1316 | ++ os_file_close(file); |
1317 | ++ } |
1318 | + ut_free(buf2); |
1319 | + mem_free(filepath); |
1320 | + } |
1321 | +@@ -4299,7 +4446,7 @@ |
1322 | idea is to read as much good data as we can and jump over bad data. |
1323 | @return 0 if ok, -1 if error even after the retries, 1 if at the end |
1324 | of the directory */ |
1325 | @@ -365,7 +418,7 @@ |
1326 | int |
1327 | fil_file_readdir_next_file( |
1328 | /*=======================*/ |
1329 | -@@ -4343,7 +4446,7 @@ |
1330 | +@@ -4343,7 +4490,7 @@ |
1331 | @return DB_SUCCESS or error number */ |
1332 | UNIV_INTERN |
1333 | ulint |
1334 | @@ -374,7 +427,7 @@ |
1335 | /*===================================*/ |
1336 | { |
1337 | int ret; |
1338 | -@@ -4399,7 +4502,9 @@ |
1339 | +@@ -4399,7 +4546,9 @@ |
1340 | dbinfo.name); |
1341 | srv_normalize_path_for_win(dbpath); |
1342 | |
1343 | @@ -385,7 +438,7 @@ |
1344 | |
1345 | if (dbdir != NULL) { |
1346 | /* printf("Opened dir %s\n", dbinfo.name); */ |
1347 | -@@ -4425,8 +4530,11 @@ |
1348 | +@@ -4425,8 +4574,11 @@ |
1349 | ".ibd")) { |
1350 | /* The name ends in .ibd; try opening |
1351 | the file */ |
1352 | @@ -398,7 +451,7 @@ |
1353 | } |
1354 | next_file_item: |
1355 | ret = fil_file_readdir_next_file(&err, |
1356 | -@@ -4598,15 +4706,97 @@ |
1357 | +@@ -4598,15 +4750,97 @@ |
1358 | "InnoDB: in InnoDB data dictionary" |
1359 | " has tablespace id %lu,\n" |
1360 | "InnoDB: but tablespace with that id" |
1361 | @@ -504,7 +557,7 @@ |
1362 | } else { |
1363 | ut_print_timestamp(stderr); |
1364 | fputs(" InnoDB: Error: table ", stderr); |
1365 | -@@ -5005,7 +5195,7 @@ |
1366 | +@@ -5005,7 +5239,7 @@ |
1367 | off the LRU list if it is in the LRU list. The caller must hold the fil_sys |
1368 | mutex. */ |
1369 | static |
1370 | @@ -513,7 +566,7 @@ |
1371 | fil_node_prepare_for_io( |
1372 | /*====================*/ |
1373 | fil_node_t* node, /*!< in: file node */ |
1374 | -@@ -5025,10 +5215,13 @@ |
1375 | +@@ -5025,10 +5259,13 @@ |
1376 | } |
1377 | |
1378 | if (node->open == FALSE) { |
1379 | @@ -528,7 +581,7 @@ |
1380 | } |
1381 | |
1382 | if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE |
1383 | -@@ -5041,6 +5234,8 @@ |
1384 | +@@ -5041,6 +5278,8 @@ |
1385 | } |
1386 | |
1387 | node->n_pending++; |
1388 | @@ -537,7 +590,7 @@ |
1389 | } |
1390 | |
1391 | /********************************************************************//** |
1392 | -@@ -5240,6 +5435,16 @@ |
1393 | +@@ -5240,6 +5479,16 @@ |
1394 | |
1395 | ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE)); |
1396 | |
1397 | @@ -691,7 +744,7 @@ |
1398 | extern char srv_adaptive_flushing; |
1399 | |
1400 | |
1401 | -@@ -247,6 +246,10 @@ |
1402 | +@@ -247,6 +246,11 @@ |
1403 | extern ulint srv_dict_size_limit; |
1404 | |
1405 | extern ulint srv_lazy_drop_table; |
1406 | @@ -699,6 +752,7 @@ |
1407 | +extern ibool srv_read_only; |
1408 | +extern ibool srv_fake_write; |
1409 | +extern ibool srv_apply_log_only; |
1410 | ++extern ibool srv_backup_mode; |
1411 | /*-------------------------------------------*/ |
1412 | |
1413 | extern ulint srv_n_rows_inserted; |
1414 | @@ -840,7 +894,35 @@ |
1415 | |
1416 | ib_uint64_t end_lsn; |
1417 | |
1418 | -@@ -2380,7 +2388,7 @@ |
1419 | +@@ -1842,6 +1850,18 @@ |
1420 | + ulint zip_size = fil_space_get_zip_size(space); |
1421 | + ulint page_no = recv_addr->page_no; |
1422 | + |
1423 | ++ /* By now we have replayed all DDL log records from the |
1424 | ++ current batch. Check if the space ID is still valid in |
1425 | ++ the entry being processed, and ignore it if it is not.*/ |
1426 | ++ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { |
1427 | ++ |
1428 | ++ ut_a(recv_sys->n_addrs); |
1429 | ++ |
1430 | ++ recv_addr->state = RECV_PROCESSED; |
1431 | ++ recv_sys->n_addrs--; |
1432 | ++ |
1433 | ++ goto next; |
1434 | ++ } |
1435 | + if (recv_addr->state == RECV_NOT_PROCESSED) { |
1436 | + if (!has_printed) { |
1437 | + ut_print_timestamp(stderr); |
1438 | +@@ -1875,7 +1895,7 @@ |
1439 | + |
1440 | + mutex_enter(&(recv_sys->mutex)); |
1441 | + } |
1442 | +- |
1443 | ++next: |
1444 | + recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); |
1445 | + } |
1446 | + |
1447 | +@@ -2380,7 +2400,7 @@ |
1448 | || type == MLOG_FILE_RENAME |
1449 | || type == MLOG_FILE_DELETE) { |
1450 | ut_a(space); |
1451 | @@ -849,7 +931,7 @@ |
1452 | if (recv_replay_file_ops) { |
1453 | |
1454 | /* In ibbackup --apply-log, replay an .ibd file |
1455 | -@@ -2403,7 +2411,7 @@ |
1456 | +@@ -2403,7 +2423,7 @@ |
1457 | ut_error; |
1458 | } |
1459 | } |
1460 | @@ -858,7 +940,7 @@ |
1461 | /* In normal mysqld crash recovery we do not try to |
1462 | replay file operations */ |
1463 | #ifdef UNIV_LOG_LSN_DEBUG |
1464 | -@@ -2820,8 +2828,11 @@ |
1465 | +@@ -2820,8 +2840,11 @@ |
1466 | |
1467 | fprintf(stderr, |
1468 | "InnoDB: Doing recovery: scanned up to" |
1469 | @@ -872,7 +954,7 @@ |
1470 | } |
1471 | } |
1472 | |
1473 | -@@ -2926,7 +2929,7 @@ |
1474 | +@@ -2926,7 +2949,7 @@ |
1475 | "InnoDB: Reading tablespace information" |
1476 | " from the .ibd files...\n"); |
1477 | |
1478 | @@ -881,7 +963,7 @@ |
1479 | |
1480 | /* If we are using the doublewrite method, we will |
1481 | check if there are half-written pages in data files, |
1482 | -@@ -2935,12 +2946,14 @@ |
1483 | +@@ -2935,12 +2958,14 @@ |
1484 | |
1485 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
1486 | |
1487 | @@ -897,7 +979,7 @@ |
1488 | } |
1489 | } |
1490 | |
1491 | -@@ -3109,6 +3122,7 @@ |
1492 | +@@ -3109,6 +3134,7 @@ |
1493 | recv_sys->recovered_lsn = checkpoint_lsn; |
1494 | |
1495 | srv_start_lsn = checkpoint_lsn; |
1496 | @@ -905,7 +987,7 @@ |
1497 | } |
1498 | |
1499 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
1500 | -@@ -3474,6 +3488,7 @@ |
1501 | +@@ -3474,6 +3500,7 @@ |
1502 | that the data dictionary tables will be free of any locks. |
1503 | The data dictionary latch should guarantee that there is at |
1504 | most one data dictionary transaction active at a time. */ |
1505 | @@ -1029,7 +1111,7 @@ |
1506 | |
1507 | /* Try to flush dirty pages so as to avoid IO bursts at |
1508 | the checkpoints. */ |
1509 | -@@ -457,6 +451,10 @@ |
1510 | +@@ -457,6 +451,11 @@ |
1511 | UNIV_INTERN ulint srv_dict_size_limit = 0; |
1512 | |
1513 | UNIV_INTERN ulint srv_lazy_drop_table = 0; |
1514 | @@ -1037,10 +1119,11 @@ |
1515 | +UNIV_INTERN ibool srv_read_only = FALSE; |
1516 | +UNIV_INTERN ibool srv_fake_write = FALSE; |
1517 | +UNIV_INTERN ibool srv_apply_log_only = FALSE; |
1518 | ++UNIV_INTERN ibool srv_backup_mode = FALSE; |
1519 | /*-------------------------------------------*/ |
1520 | UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; |
1521 | UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; |
1522 | -@@ -1137,7 +1135,7 @@ |
1523 | +@@ -1137,7 +1136,7 @@ |
1524 | } |
1525 | |
1526 | /* Initialize some INFORMATION SCHEMA internal structures */ |
1527 | @@ -1049,7 +1132,7 @@ |
1528 | } |
1529 | |
1530 | /*********************************************************************//** |
1531 | -@@ -1148,6 +1146,7 @@ |
1532 | +@@ -1148,6 +1147,7 @@ |
1533 | /*==========*/ |
1534 | { |
1535 | os_fast_mutex_free(&srv_conc_mutex); |
1536 | @@ -1057,7 +1140,7 @@ |
1537 | mem_free(srv_conc_slots); |
1538 | srv_conc_slots = NULL; |
1539 | |
1540 | -@@ -1161,6 +1160,7 @@ |
1541 | +@@ -1161,6 +1161,7 @@ |
1542 | srv_mysql_table = NULL; |
1543 | |
1544 | trx_i_s_cache_free(trx_i_s_cache); |
1545 | @@ -1065,7 +1148,7 @@ |
1546 | } |
1547 | |
1548 | /*********************************************************************//** |
1549 | -@@ -1886,7 +1886,7 @@ |
1550 | +@@ -1886,7 +1887,7 @@ |
1551 | } |
1552 | |
1553 | /* Record the lock wait time for this thread */ |
1554 | @@ -1074,7 +1157,7 @@ |
1555 | } |
1556 | |
1557 | if (trx->was_chosen_as_deadlock_victim) { |
1558 | -@@ -2842,36 +2842,6 @@ |
1559 | +@@ -2842,36 +2843,6 @@ |
1560 | old_sema = sema; |
1561 | } |
1562 | |
1563 | |
1564 | === modified file 'src/fil_cur.cc' |
1565 | --- src/fil_cur.cc 2013-04-29 06:43:29 +0000 |
1566 | +++ src/fil_cur.cc 2013-05-08 05:18:19 +0000 |
1567 | @@ -74,6 +74,55 @@ |
1568 | |
1569 | } |
1570 | |
1571 | +/**********************************************************************//** |
1572 | +Closes a file. */ |
1573 | +static |
1574 | +void |
1575 | +xb_fil_node_close_file( |
1576 | +/*===================*/ |
1577 | + fil_node_t* node) /*!< in: file node */ |
1578 | +{ |
1579 | + ibool ret; |
1580 | + |
1581 | + mutex_enter(&fil_system->mutex); |
1582 | + |
1583 | + ut_ad(node); |
1584 | + ut_a(node->n_pending == 0); |
1585 | + ut_a(node->n_pending_flushes == 0); |
1586 | +#if MYSQL_VERSION_ID >= 50600 |
1587 | + ut_a(!node->being_extended); |
1588 | +#endif |
1589 | + |
1590 | + if (!node->open) { |
1591 | + |
1592 | + mutex_exit(&fil_system->mutex); |
1593 | + |
1594 | + return; |
1595 | + } |
1596 | + |
1597 | + ret = os_file_close(node->handle); |
1598 | + ut_a(ret); |
1599 | + |
1600 | + node->open = FALSE; |
1601 | + |
1602 | + ut_a(fil_system->n_open > 0); |
1603 | + fil_system->n_open--; |
1604 | +#if MYSQL_VERSION_ID >= 50600 |
1605 | + fil_n_file_opened--; |
1606 | +#endif |
1607 | + |
1608 | + if (node->space->purpose == FIL_TABLESPACE && |
1609 | + !trx_sys_sys_space(node->space->id)) { |
1610 | + |
1611 | + ut_a(UT_LIST_GET_LEN(fil_system->LRU) > 0); |
1612 | + |
1613 | + /* The node is in the LRU list, remove it */ |
1614 | + UT_LIST_REMOVE(LRU, fil_system->LRU, node); |
1615 | + } |
1616 | + |
1617 | + mutex_exit(&fil_system->mutex); |
1618 | +} |
1619 | + |
1620 | /************************************************************************ |
1621 | Open a source file cursor and initialize the associated read filter. |
1622 | |
1623 | @@ -90,11 +139,12 @@ |
1624 | ulint page_size; |
1625 | ulint page_size_shift; |
1626 | ulint zip_size; |
1627 | + ibool success; |
1628 | |
1629 | /* Initialize these first so xb_fil_cur_close() handles them correctly |
1630 | in case of error */ |
1631 | cursor->orig_buf = NULL; |
1632 | - cursor->file = XB_FILE_UNDEFINED; |
1633 | + cursor->node = NULL; |
1634 | |
1635 | cursor->space_id = node->space->id; |
1636 | cursor->is_system = trx_sys_sys_space(node->space->id); |
1637 | @@ -109,31 +159,56 @@ |
1638 | xb_get_relative_path(cursor->abs_path, cursor->is_system), |
1639 | sizeof(cursor->rel_path)); |
1640 | |
1641 | - /* Open the file */ |
1642 | - |
1643 | - if (my_stat(node->name, &cursor->statinfo, MYF(MY_WME)) == NULL) { |
1644 | - msg("[%02u] xtrabackup: Warning: cannot stat %s\n", |
1645 | - thread_n, node->name); |
1646 | - return(XB_FIL_CUR_SKIP); |
1647 | - } |
1648 | - |
1649 | - ibool success; |
1650 | - |
1651 | - cursor->file = |
1652 | - xb_file_create_no_error_handling(node->name, |
1653 | + /* In the backup mode we should already have a tablespace handle created |
1654 | + by fil_load_single_table_tablespace() unless it is a system |
1655 | + tablespace. Otherwise we open the file here. */ |
1656 | + if (cursor->is_system || !srv_backup_mode) { |
1657 | + node->handle = |
1658 | + xb_file_create_no_error_handling(node->name, |
1659 | OS_FILE_OPEN, |
1660 | OS_FILE_READ_ONLY, |
1661 | &success); |
1662 | - if (!success) { |
1663 | - /* The following call prints an error message */ |
1664 | - os_file_get_last_error(TRUE); |
1665 | - |
1666 | - msg("[%02u] xtrabackup: Warning: cannot open %s\n" |
1667 | - "[%02u] xtrabackup: Warning: We assume the " |
1668 | - "table was dropped or renamed during " |
1669 | - "xtrabackup execution and ignore the file.\n", |
1670 | - thread_n, node->name, thread_n); |
1671 | - return(XB_FIL_CUR_SKIP); |
1672 | + if (!success) { |
1673 | + /* The following call prints an error message */ |
1674 | + os_file_get_last_error(TRUE); |
1675 | + |
1676 | + msg("[%02u] xtrabackup: error: cannot open " |
1677 | + "tablespace %s\n", |
1678 | + thread_n, cursor->abs_path); |
1679 | + |
1680 | + return(XB_FIL_CUR_ERROR); |
1681 | + } |
1682 | + mutex_enter(&fil_system->mutex); |
1683 | + |
1684 | + node->open = TRUE; |
1685 | + |
1686 | + fil_system->n_open++; |
1687 | +#if MYSQL_VERSION_ID >= 50600 |
1688 | + fil_n_file_opened++; |
1689 | +#endif |
1690 | + |
1691 | + if (node->space->purpose == FIL_TABLESPACE && |
1692 | + !trx_sys_sys_space(node->space->id)) { |
1693 | + |
1694 | + /* Put the node to the LRU list */ |
1695 | + UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node); |
1696 | + } |
1697 | + |
1698 | + mutex_exit(&fil_system->mutex); |
1699 | + } |
1700 | + |
1701 | + ut_ad(node->open); |
1702 | + |
1703 | + cursor->node = node; |
1704 | + cursor->file = node->handle; |
1705 | + |
1706 | + if (my_fstat(cursor->file, &cursor->statinfo, MYF(MY_WME))) { |
1707 | + msg("[%02u] xtrabackup: error: cannot stat %s\n", |
1708 | + thread_n, cursor->abs_path); |
1709 | + |
1710 | + xb_fil_cur_close(cursor); |
1711 | + |
1712 | + return(XB_FIL_CUR_ERROR); |
1713 | } |
1714 | |
1715 | xb_file_set_nocache(cursor->file, node->name, "OPEN"); |
1716 | @@ -142,7 +217,7 @@ |
1717 | /* Determine the page size */ |
1718 | zip_size = xb_get_zip_size(cursor->file); |
1719 | if (zip_size == ULINT_UNDEFINED) { |
1720 | - os_file_close(cursor->file); |
1721 | + xb_fil_cur_close(cursor); |
1722 | return(XB_FIL_CUR_SKIP); |
1723 | } else if (zip_size) { |
1724 | page_size = zip_size; |
1725 | @@ -230,7 +305,8 @@ |
1726 | cursor->buf_offset = offset; |
1727 | cursor->buf_page_no = (ulint) (offset >> cursor->page_size_shift); |
1728 | |
1729 | - success = xb_os_file_read(cursor->file, cursor->buf, offset, to_read); |
1730 | + success = xb_os_file_read(cursor->file, cursor->buf, offset, |
1731 | + to_read); |
1732 | if (!success) { |
1733 | return(XB_FIL_CUR_ERROR); |
1734 | } |
1735 | @@ -294,7 +370,8 @@ |
1736 | if (cursor->orig_buf != NULL) { |
1737 | ut_free(cursor->orig_buf); |
1738 | } |
1739 | - if (cursor->file != XB_FILE_UNDEFINED) { |
1740 | - os_file_close(cursor->file); |
1741 | + if (cursor->node != NULL) { |
1742 | + xb_fil_node_close_file(cursor->node); |
1743 | + cursor->file = XB_FILE_UNDEFINED; |
1744 | } |
1745 | } |
1746 | |
1747 | === modified file 'src/fil_cur.h' |
1748 | --- src/fil_cur.h 2013-04-23 07:44:24 +0000 |
1749 | +++ src/fil_cur.h 2013-05-08 05:18:19 +0000 |
1750 | @@ -31,6 +31,7 @@ |
1751 | |
1752 | struct xb_fil_cur_t { |
1753 | os_file_t file; /*!< source file handle */ |
1754 | + fil_node_t* node; /*!< source tablespace node */ |
1755 | char rel_path[FN_REFLEN]; |
1756 | /*!< normalized file path */ |
1757 | char abs_path[FN_REFLEN]; |
1758 | |
1759 | === modified file 'src/xtrabackup.cc' |
1760 | --- src/xtrabackup.cc 2013-05-07 13:28:22 +0000 |
1761 | +++ src/xtrabackup.cc 2013-05-08 05:18:19 +0000 |
1762 | @@ -1813,6 +1813,55 @@ |
1763 | return(zip_size); |
1764 | } |
1765 | |
1766 | +/**********************************************************************//** |
1767 | +Closes a file. */ |
1768 | +static |
1769 | +void |
1770 | +xb_fil_node_close_file( |
1771 | +/*===================*/ |
1772 | + fil_node_t* node) /*!< in: file node */ |
1773 | +{ |
1774 | + ibool ret; |
1775 | + |
1776 | + mutex_enter(&fil_system->mutex); |
1777 | + |
1778 | + ut_ad(node); |
1779 | + ut_a(node->n_pending == 0); |
1780 | + ut_a(node->n_pending_flushes == 0); |
1781 | +#if MYSQL_VERSION_ID >= 50600 |
1782 | + ut_a(!node->being_extended); |
1783 | +#endif |
1784 | + |
1785 | + if (!node->open) { |
1786 | + |
1787 | + mutex_exit(&fil_system->mutex); |
1788 | + |
1789 | + return; |
1790 | + } |
1791 | + |
1792 | + ret = os_file_close(node->handle); |
1793 | + ut_a(ret); |
1794 | + |
1795 | + node->open = FALSE; |
1796 | + |
1797 | + ut_a(fil_system->n_open > 0); |
1798 | + fil_system->n_open--; |
1799 | +#if MYSQL_VERSION_ID >= 50600 |
1800 | + fil_n_file_opened--; |
1801 | +#endif |
1802 | + |
1803 | + if (node->space->purpose == FIL_TABLESPACE && |
1804 | + !trx_sys_sys_space(node->space->id)) { |
1805 | + |
1806 | + ut_a(UT_LIST_GET_LEN(fil_system->LRU) > 0); |
1807 | + |
1808 | + /* The node is in the LRU list, remove it */ |
1809 | + UT_LIST_REMOVE(LRU, fil_system->LRU, node); |
1810 | + } |
1811 | + |
1812 | + mutex_exit(&fil_system->mutex); |
1813 | +} |
1814 | + |
1815 | /* TODO: We may tune the behavior (e.g. by fil_aio)*/ |
1816 | |
1817 | static |
1818 | @@ -2497,8 +2546,7 @@ |
1819 | srv_n_write_io_threads, |
1820 | SRV_MAX_N_PENDING_SYNC_IOS); |
1821 | |
1822 | - fil_init(srv_file_per_table ? 50000 : 5000, |
1823 | - srv_max_n_open_files); |
1824 | + fil_init(srv_file_per_table ? 50000 : 5000, LONG_MAX); |
1825 | |
1826 | fsp_init(); |
1827 | |
1828 | @@ -2541,11 +2589,6 @@ |
1829 | return(DB_ERROR); |
1830 | } |
1831 | |
1832 | - err = fil_load_single_table_tablespaces(xb_check_if_open_tablespace); |
1833 | - if (err != DB_SUCCESS) { |
1834 | - return(err); |
1835 | - } |
1836 | - |
1837 | #if MYSQL_VERSION_ID >= 50600 |
1838 | /* Add separate undo tablespaces to fil_system */ |
1839 | |
1840 | @@ -2558,6 +2601,15 @@ |
1841 | } |
1842 | #endif |
1843 | |
1844 | + /* It is important to call fil_load_single_table_tablespace() after |
1845 | + srv_undo_tablespaces_init(), because fil_is_user_tablespace_id() * |
1846 | + relies on srv_undo_tablespaces_open to be properly initialized */ |
1847 | + |
1848 | + err = fil_load_single_table_tablespaces(xb_check_if_open_tablespace); |
1849 | + if (err != DB_SUCCESS) { |
1850 | + return(err); |
1851 | + } |
1852 | + |
1853 | return(DB_SUCCESS); |
1854 | } |
1855 | |
1856 | @@ -2851,6 +2903,8 @@ |
1857 | |
1858 | xb_set_innodb_read_only(); |
1859 | |
1860 | + srv_backup_mode = TRUE; |
1861 | + |
1862 | /* initialize components */ |
1863 | if(innodb_init_param()) |
1864 | exit(EXIT_FAILURE); |
1865 | |
1866 | === renamed file 'test/t/bug722638.sh' => 'test/t/ddl.sh' |
1867 | --- test/t/bug722638.sh 2012-06-04 18:29:48 +0000 |
1868 | +++ test/t/ddl.sh 2013-05-08 05:18:19 +0000 |
1869 | @@ -1,7 +1,9 @@ |
1870 | -######################################################################## |
1871 | -# Bug #722638: xtrabackup: taking backup while tables are droped and |
1872 | +############################################################################ |
1873 | +# Bug #722638: xtrabackup: taking backup while tables are droped and |
1874 | # created breaks backup |
1875 | -######################################################################## |
1876 | +# |
1877 | +# Bug #1079700: Issues with renaming/rotating tables during the backup stage |
1878 | +############################################################################ |
1879 | |
1880 | . inc/common.sh |
1881 | |
1882 | @@ -10,7 +12,11 @@ |
1883 | exit $SKIPPED_EXIT_CODE |
1884 | fi |
1885 | |
1886 | -start_server --innodb_file_per_table |
1887 | +MYSQLD_EXTRA_MY_CNF_OPTS=" |
1888 | +innodb_file_per_table |
1889 | +" |
1890 | + |
1891 | +start_server |
1892 | |
1893 | run_cmd $MYSQL $MYSQL_ARGS test <<EOF |
1894 | |
1895 | @@ -26,8 +32,19 @@ |
1896 | CREATE TABLE t4_old(a INT) ENGINE=InnoDB; |
1897 | INSERT INTO t4_old VALUES (1), (2), (3); |
1898 | |
1899 | +CREATE TABLE t5(a INT) ENGINE=InnoDB; |
1900 | +INSERT INTO t5 VALUES (1), (2), (3); |
1901 | + |
1902 | +CREATE TABLE t6(c CHAR(1)) ENGINE=InnoDB; |
1903 | +INSERT INTO t6 VALUES ('a'), ('b'), ('c'); |
1904 | + |
1905 | EOF |
1906 | |
1907 | +# Make a checkpoint so that original tablespace creation events are not in the |
1908 | +# xtrabackup log |
1909 | +shutdown_server |
1910 | +start_server |
1911 | + |
1912 | mkdir -p $topdir/backup |
1913 | |
1914 | # Backup |
1915 | @@ -70,13 +87,18 @@ |
1916 | ALTER TABLE t4_old RENAME t4; |
1917 | INSERT INTO t4 VALUES (7), (8), (9); |
1918 | |
1919 | +INSERT INTO t5 VALUES (4), (5), (6); |
1920 | +INSERT INTO t6 VALUES ('d'), ('e'), ('f'); |
1921 | + |
1922 | +# Rotate tables t5 and t6 |
1923 | +RENAME TABLE t5 TO temp, t6 TO t5, temp TO t6; |
1924 | + |
1925 | +INSERT INTO t5 VALUES ('g'), ('h'), ('i'); |
1926 | +INSERT INTO t6 VALUES (7), (8), (9); |
1927 | + |
1928 | EOF |
1929 | |
1930 | -# Calculate checksums |
1931 | -checksum_t1=`checksum_table test t1` |
1932 | -checksum_t2=`checksum_table test t2` |
1933 | -checksum_t3=`checksum_table test t3` |
1934 | -checksum_t4=`checksum_table test t4` |
1935 | +record_db_state test |
1936 | |
1937 | # Resume xtrabackup |
1938 | vlog "Resuming xtrabackup" |
1939 | @@ -84,6 +106,8 @@ |
1940 | |
1941 | run_cmd wait $job_pid |
1942 | |
1943 | +# exit 1 |
1944 | + |
1945 | # Prepare |
1946 | xtrabackup --datadir=$mysql_datadir --prepare --target-dir=$topdir/backup |
1947 | |
1948 | @@ -94,25 +118,7 @@ |
1949 | $mysql_datadir/test/*.ibd |
1950 | cp -r $topdir/backup/* $mysql_datadir |
1951 | |
1952 | -start_server --innodb_file_per_table |
1953 | - |
1954 | -# Verify checksums |
1955 | -checksum_t1_new=`checksum_table test t1` |
1956 | -checksum_t2_new=`checksum_table test t2` |
1957 | -checksum_t3_new=`checksum_table test t3` |
1958 | -checksum_t4_new=`checksum_table test t4` |
1959 | -vlog "Checksums (old/new):" |
1960 | -vlog "t1: $checksum_t1/$checksum_t1_new" |
1961 | -vlog "t2: $checksum_t2/$checksum_t2_new" |
1962 | -vlog "t3: $checksum_t3/$checksum_t3_new" |
1963 | -vlog "t4: $checksum_t4/$checksum_t4_new" |
1964 | - |
1965 | -if [ "$checksum_t1" = "$checksum_t1_new" -a \ |
1966 | - "$checksum_t2" = "$checksum_t2_new" -a \ |
1967 | - "$checksum_t3" = "$checksum_t3_new" -a \ |
1968 | - "$checksum_t4" = "$checksum_t4_new" ]; then |
1969 | - exit 0 |
1970 | -fi |
1971 | - |
1972 | -vlog "Checksums do not match" |
1973 | -exit -1 |
1974 | +start_server |
1975 | + |
1976 | +# Verify backup |
1977 | +verify_db_state test |
Same comments as for the 2.0 MP.