Merge lp:~akopytov/percona-xtrabackup/compact-backups into lp:percona-xtrabackup/2.1
- compact-backups
- Merge into 2.1
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Stewart Smith | ||||||||||||
Approved revision: | no longer in the source branch. | ||||||||||||
Merged at revision: | 486 | ||||||||||||
Proposed branch: | lp:~akopytov/percona-xtrabackup/compact-backups | ||||||||||||
Merge into: | lp:percona-xtrabackup/2.1 | ||||||||||||
Diff against target: |
3973 lines (+2019/-639) 25 files modified
innobackupex (+22/-2) patches/innodb51.patch (+128/-65) patches/innodb55.patch (+142/-63) patches/xtradb51.patch (+125/-59) patches/xtradb55.patch (+138/-59) src/Makefile (+4/-3) src/compact.c (+960/-0) src/compact.h (+44/-0) src/datasink.c (+1/-0) src/ds_tmpfile.c (+1/-1) src/fil_cur.c (+5/-3) src/fil_cur.h (+2/-1) src/innodb_int.c (+45/-0) src/innodb_int.h (+22/-0) src/write_filt.c (+1/-102) src/write_filt.h (+1/-5) src/xb0xb.h (+40/-0) src/xbstream.c (+3/-2) src/xtrabackup.c (+251/-249) src/xtrabackup.h (+28/-0) test/inc/incremental_sample-db/incremental_sample-schema.sql (+3/-2) test/t/compact.sh (+5/-6) test/t/compact_compressed.sh (+33/-9) test/testrun.sh (+2/-1) utils/build.sh (+13/-7) |
||||||||||||
To merge this branch: | bzr merge lp:~akopytov/percona-xtrabackup/compact-backups | ||||||||||||
Related bugs: |
|
||||||||||||
Related blueprints: |
Compact backups support
(High)
Drop --remote-host support
(High)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stewart Smith (community) | Approve | ||
Hrvoje Matijakovic | doc | Pending | |
Review via email: mp+139157@code.launchpad.net |
Commit message
Description of the change
Alexey Kopytov (akopytov) wrote : | # |
Vadim Tkachenko (vadim-tk) wrote : | # |
Included Hrvoje to make sure that documentation is updated
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
This is not review. Just revision comment for rev. 460 caught my eye.
Alexey Kopytov (akopytov) wrote : | # |
Another Jenkins build with recent bugfixes and merges with sporadic test suite failures: http://
I also had to disable UNIV_SYNC_DEBUG and UNIV_MEM_DEBUG for debug builds, as compact_compress alone took more than 30 minutes on my not-so-slow laptop with most time spent in UNIV_SYNC_DEBUG and UNIV_MEM_DEBUG code paths when rebuilding indexes.
Stewart Smith (stewart) wrote : | # |
So, I have some thoughts about if we should just use sparse files instead and be done with it, and also we naturally have more QA to do, but I'm pretty happy that this is able to be merged now without adversely impacting other features.
Preview Diff
1 | === modified file 'innobackupex' |
2 | --- innobackupex 2013-01-14 04:46:19 +0000 |
3 | +++ innobackupex 2013-01-14 11:06:22 +0000 |
4 | @@ -118,6 +118,7 @@ |
5 | my $option_safe_slave_backup_timeout = 300; |
6 | |
7 | my $option_compact = ''; |
8 | +my $option_rebuild_indexes = ''; |
9 | |
10 | # name of the my.cnf configuration file |
11 | #my $config_file = ''; |
12 | @@ -699,6 +700,7 @@ |
13 | '\.\.?|backup-my\.cnf|xtrabackup_logfile|' . |
14 | 'xtrabackup_binary|xtrabackup_binlog_info|xtrabackup_checkpoints|' . |
15 | '.*\.qp|' . |
16 | + '.*\.pmap|.*\.tmp|' . |
17 | $iblog_files; |
18 | my $compressed_data_file = '.*\.ibz$'; |
19 | my $file; |
20 | @@ -806,6 +808,7 @@ |
21 | sub apply_log { |
22 | my $rcode; |
23 | my $cmdline = ''; |
24 | + my $cmdline_copy = ''; |
25 | my $options = ''; |
26 | |
27 | if ($option_defaults_file) { |
28 | @@ -839,6 +842,13 @@ |
29 | |
30 | # run ibbackup as a child process |
31 | $cmdline = "$option_ibbackup_binary $options"; |
32 | + |
33 | + # Only use --rebuild-indexes in the first xtrabackup call |
34 | + $cmdline_copy = $cmdline; |
35 | + if ($option_rebuild_indexes) { |
36 | + $cmdline = $cmdline . " --rebuild-indexes" |
37 | + } |
38 | + |
39 | $now = current_time(); |
40 | print STDERR "\n$now $prefix Starting ibbackup with command: $cmdline\n\n"; |
41 | $rcode = system("$cmdline"); |
42 | @@ -850,6 +860,7 @@ |
43 | # We should not create ib_logfile files if we prepare for following incremental applies |
44 | # Also we do not prepare ib_logfile if we applied incremental changes |
45 | if (!( ($option_redo_only) or ($option_incremental_dir))) { |
46 | + $cmdline = $cmdline_copy; |
47 | $now = current_time(); |
48 | print STDERR "\n$now $prefix Restarting xtrabackup with command: $cmdline\nfor creating ib_logfile*\n\n"; |
49 | $rcode = system("$cmdline"); |
50 | @@ -1036,8 +1047,12 @@ |
51 | if ($option_stream) { |
52 | $options = $options . " --stream=$option_stream"; |
53 | } |
54 | + |
55 | if ($option_compact) { |
56 | - $options = $options. " --compact"; |
57 | + $options = $options . " --compact"; |
58 | + } |
59 | + if ($option_rebuild_indexes) { |
60 | + $options = $options . " --rebuild-indexes"; |
61 | } |
62 | |
63 | $cmdline = "$option_ibbackup_binary $options"; |
64 | @@ -1753,7 +1768,8 @@ |
65 | 'parallel=i' => \$option_parallel, |
66 | 'safe-slave-backup' => \$option_safe_slave_backup, |
67 | 'safe-slave-backup-timeout=i' => \$option_safe_slave_backup_timeout, |
68 | - 'compact' => \$option_compact |
69 | + 'compact' => \$option_compact, |
70 | + 'rebuild-indexes' => \$option_rebuild_indexes |
71 | ); |
72 | |
73 | if (!$rcode) { |
74 | @@ -2800,6 +2816,10 @@ |
75 | |
76 | This option specifies the port to use when connecting to the database server with TCP/IP. The option accepts a string argument. It is passed to the mysql child process. It is passed to the mysql child process without alteration. See mysql --help for details. |
77 | |
78 | +=item --rebuild-indexes |
79 | + |
80 | +This option only has effect when used together with the --apply-log option and is passed directly to xtrabackup. When used, makes xtrabackup rebuild all secondary indexes after applying the log. This option is normally used to prepare compact backups. See the XtraBackup manual for more information. |
81 | + |
82 | =item --redo-only |
83 | |
84 | This option is passed directly to xtrabackup's --apply-log-only option. This forces xtrabackup to skip the "rollback" phase and do a "redo" only. This is necessary if the backup will have incremental changes applied to it later. See the xtrabackup documentation for details. |
85 | |
86 | === modified file 'patches/innodb51.patch' |
87 | --- patches/innodb51.patch 2012-11-14 04:46:11 +0000 |
88 | +++ patches/innodb51.patch 2013-01-14 11:06:22 +0000 |
89 | @@ -30,7 +30,15 @@ |
90 | n_not_null[i]++; |
91 | --- a/storage/innodb_plugin/buf/buf0buf.c |
92 | +++ b/storage/innodb_plugin/buf/buf0buf.c |
93 | -@@ -358,7 +358,7 @@ |
94 | +@@ -51,6 +51,7 @@ |
95 | + #include "dict0dict.h" |
96 | + #include "log0recv.h" |
97 | + #include "page0zip.h" |
98 | ++#include "xb0xb.h" |
99 | + |
100 | + /* |
101 | + IMPLEMENTATION OF THE BUFFER POOL |
102 | +@@ -358,7 +359,7 @@ |
103 | return(TRUE); |
104 | } |
105 | |
106 | @@ -39,7 +47,15 @@ |
107 | if (recv_lsn_checks_on) { |
108 | ib_uint64_t current_lsn; |
109 | |
110 | -@@ -1690,7 +1690,9 @@ |
111 | +@@ -670,6 +671,7 @@ |
112 | + block->page.in_flush_list = FALSE; |
113 | + block->page.in_free_list = FALSE; |
114 | + block->page.in_LRU_list = FALSE; |
115 | ++ block->page.is_compacted = FALSE; |
116 | + block->in_unzip_LRU_list = FALSE; |
117 | + #endif /* UNIV_DEBUG */ |
118 | + #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG |
119 | +@@ -1690,7 +1692,9 @@ |
120 | ut_ad(zip_size == fil_space_get_zip_size(space)); |
121 | ut_ad(ut_is_2pow(zip_size)); |
122 | #ifndef UNIV_LOG_DEBUG |
123 | @@ -50,12 +66,26 @@ |
124 | #endif |
125 | buf_pool->stat.n_page_gets++; |
126 | loop: |
127 | -@@ -2894,7 +2896,7 @@ |
128 | +@@ -2802,6 +2806,12 @@ |
129 | + frame = ((buf_block_t*) bpage)->frame; |
130 | + } |
131 | + |
132 | ++ /* Do not validate, recover and apply change buffer entries to |
133 | ++ bogus pages which replace skipped pages in compact backups. */ |
134 | ++ if (srv_compact_backup && buf_page_is_compacted(frame)) { |
135 | ++ bpage->is_compacted = TRUE; |
136 | ++ } |
137 | ++ |
138 | + /* If this page is not uninitialized and not in the |
139 | + doublewrite buffer, then the page number and space id |
140 | + should be the same as in block. */ |
141 | +@@ -2894,7 +2904,8 @@ |
142 | recv_recover_page(TRUE, (buf_block_t*) bpage); |
143 | } |
144 | |
145 | - if (uncompressed && !recv_no_ibuf_operations) { |
146 | -+ if (uncompressed && !recv_no_ibuf_operations && !srv_fake_write) { |
147 | ++ if (uncompressed && !recv_no_ibuf_operations && |
148 | ++ !srv_fake_write && !bpage->is_compacted) { |
149 | ibuf_merge_or_delete_for_page( |
150 | (buf_block_t*) bpage, bpage->space, |
151 | bpage->offset, buf_page_get_zip_size(bpage), |
152 | @@ -783,7 +813,7 @@ |
153 | /* In this fastest shutdown we do not flush the buffer pool: |
154 | --- a/storage/innodb_plugin/log/log0recv.c |
155 | +++ b/storage/innodb_plugin/log/log0recv.c |
156 | -@@ -42,27 +42,27 @@ |
157 | +@@ -42,27 +42,28 @@ |
158 | #include "trx0undo.h" |
159 | #include "trx0rec.h" |
160 | #include "fil0fil.h" |
161 | @@ -797,6 +827,7 @@ |
162 | # include "sync0sync.h" |
163 | -#else /* !UNIV_HOTBACKUP */ |
164 | +//#else /* !UNIV_HOTBACKUP */ |
165 | ++#include "xb0xb.h" |
166 | |
167 | /** This is set to FALSE if the backup was originally taken with the |
168 | ibbackup --include regexp option: then we do not want to create tables in |
169 | @@ -815,7 +846,7 @@ |
170 | |
171 | /** The recovery system */ |
172 | UNIV_INTERN recv_sys_t* recv_sys = NULL; |
173 | -@@ -251,7 +251,7 @@ |
174 | +@@ -251,7 +252,7 @@ |
175 | { |
176 | recv_lsn_checks_on = FALSE; |
177 | |
178 | @@ -824,7 +855,7 @@ |
179 | |
180 | recv_recovery_on = FALSE; |
181 | |
182 | -@@ -277,7 +277,7 @@ |
183 | +@@ -277,7 +278,7 @@ |
184 | |
185 | recv_max_parsed_page_no = 0; |
186 | |
187 | @@ -833,7 +864,7 @@ |
188 | |
189 | recv_max_page_lsn = 0; |
190 | } |
191 | -@@ -613,7 +613,7 @@ |
192 | +@@ -613,7 +614,7 @@ |
193 | /***********************************************************************//** |
194 | Checks the consistency of the checkpoint info |
195 | @return TRUE if ok */ |
196 | @@ -842,7 +873,7 @@ |
197 | ibool |
198 | recv_check_cp_is_consistent( |
199 | /*========================*/ |
200 | -@@ -643,7 +643,7 @@ |
201 | +@@ -643,7 +644,7 @@ |
202 | /********************************************************//** |
203 | Looks for the maximum consistent checkpoint from the log groups. |
204 | @return error code or DB_SUCCESS */ |
205 | @@ -851,7 +882,7 @@ |
206 | ulint |
207 | recv_find_max_checkpoint( |
208 | /*=====================*/ |
209 | -@@ -818,7 +818,7 @@ |
210 | +@@ -818,7 +819,7 @@ |
211 | InnoDB-3.23.52 where the checksum field contains the log block number. |
212 | @return TRUE if ok, or if the log block may be in the format of InnoDB |
213 | version predating 3.23.52 */ |
214 | @@ -860,7 +891,7 @@ |
215 | ibool |
216 | log_block_checksum_is_ok_or_old_format( |
217 | /*===================================*/ |
218 | -@@ -1486,6 +1486,7 @@ |
219 | +@@ -1486,6 +1487,7 @@ |
220 | buf_block_get_page_no(block)); |
221 | |
222 | if ((recv_addr == NULL) |
223 | @@ -868,7 +899,25 @@ |
224 | || (recv_addr->state == RECV_BEING_PROCESSED) |
225 | || (recv_addr->state == RECV_PROCESSED)) { |
226 | |
227 | -@@ -2297,7 +2298,7 @@ |
228 | +@@ -1575,9 +1577,16 @@ |
229 | + if (page_zip) { |
230 | + memset(FIL_PAGE_LSN + page_zip->data, 0, 8); |
231 | + } |
232 | ++ |
233 | ++ if (block->page.is_compacted) { |
234 | ++ |
235 | ++ ut_ad(srv_compact_backup); |
236 | ++ |
237 | ++ block->page.is_compacted = FALSE; |
238 | ++ } |
239 | + } |
240 | + |
241 | +- if (recv->start_lsn >= page_lsn) { |
242 | ++ if (!block->page.is_compacted && recv->start_lsn >= page_lsn) { |
243 | + |
244 | + ib_uint64_t end_lsn; |
245 | + |
246 | +@@ -2297,7 +2306,7 @@ |
247 | || type == MLOG_FILE_RENAME |
248 | || type == MLOG_FILE_DELETE) { |
249 | ut_a(space); |
250 | @@ -877,7 +926,7 @@ |
251 | if (recv_replay_file_ops) { |
252 | |
253 | /* In ibbackup --apply-log, replay an .ibd file |
254 | -@@ -2320,7 +2321,7 @@ |
255 | +@@ -2320,7 +2329,7 @@ |
256 | ut_error; |
257 | } |
258 | } |
259 | @@ -886,7 +935,7 @@ |
260 | /* In normal mysqld crash recovery we do not try to |
261 | replay file operations */ |
262 | #ifdef UNIV_LOG_LSN_DEBUG |
263 | -@@ -2737,8 +2738,11 @@ |
264 | +@@ -2737,8 +2746,11 @@ |
265 | |
266 | fprintf(stderr, |
267 | "InnoDB: Doing recovery: scanned up to" |
268 | @@ -900,7 +949,7 @@ |
269 | } |
270 | } |
271 | |
272 | -@@ -2850,12 +2854,14 @@ |
273 | +@@ -2850,12 +2862,14 @@ |
274 | |
275 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
276 | |
277 | @@ -916,7 +965,7 @@ |
278 | } |
279 | } |
280 | |
281 | -@@ -3005,6 +3011,7 @@ |
282 | +@@ -3005,6 +3019,7 @@ |
283 | recv_sys->recovered_lsn = checkpoint_lsn; |
284 | |
285 | srv_start_lsn = checkpoint_lsn; |
286 | @@ -924,7 +973,7 @@ |
287 | } |
288 | |
289 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
290 | -@@ -3286,6 +3293,7 @@ |
291 | +@@ -3286,6 +3301,7 @@ |
292 | that the data dictionary tables will be free of any locks. |
293 | The data dictionary latch should guarantee that there is at |
294 | most one data dictionary transaction active at a time. */ |
295 | @@ -1007,46 +1056,6 @@ |
296 | #endif |
297 | } |
298 | |
299 | ---- a/storage/innodb_plugin/row/row0merge.c |
300 | -+++ b/storage/innodb_plugin/row/row0merge.c |
301 | -@@ -453,7 +453,9 @@ |
302 | - rec = rec_convert_dtuple_to_rec(*buf, index, tuple, n_ext); |
303 | - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); |
304 | - |
305 | -- innobase_rec_to_mysql(dup->table, rec, index, offsets); |
306 | -+ //innobase_rec_to_mysql(dup->table, rec, index, offsets); |
307 | -+ fprintf(stderr, "InnoDB: Error: row_merge_dup_report() is called.\n"); |
308 | -+ ut_error; |
309 | - |
310 | - mem_heap_free(heap); |
311 | - } |
312 | -@@ -1457,8 +1459,12 @@ |
313 | - case 0: |
314 | - if (UNIV_UNLIKELY |
315 | - (dict_index_is_unique(index) && !null_eq)) { |
316 | -- innobase_rec_to_mysql(table, mrec0, |
317 | -- index, offsets0); |
318 | -+ //innobase_rec_to_mysql(table, mrec0, |
319 | -+ // index, offsets0); |
320 | -+ (void) table; |
321 | -+ fprintf(stderr, "InnoDB: Error: " |
322 | -+ "row_merge_blocks() is called.\n"); |
323 | -+ ut_error; |
324 | - mem_heap_free(heap); |
325 | - return(DB_DUPLICATE_KEY); |
326 | - } |
327 | -@@ -2584,7 +2590,10 @@ |
328 | - |
329 | - /* Reset the MySQL row buffer that is used when reporting |
330 | - duplicate keys. */ |
331 | -- innobase_rec_reset(table); |
332 | -+ //innobase_rec_reset(table); |
333 | -+ fprintf(stderr, "InnoDB: Error: row_merge_build_indexes() is called." |
334 | -+ "\n"); |
335 | -+ ut_error; |
336 | - |
337 | - /* Read clustered index of the table and create files for |
338 | - secondary index entries for merge sort */ |
339 | --- a/storage/innodb_plugin/srv/srv0srv.c |
340 | +++ b/storage/innodb_plugin/srv/srv0srv.c |
341 | @@ -374,6 +374,9 @@ |
342 | @@ -1086,7 +1095,15 @@ |
343 | /*********************************************************************//** |
344 | --- a/storage/innodb_plugin/srv/srv0start.c |
345 | +++ b/storage/innodb_plugin/srv/srv0start.c |
346 | -@@ -94,6 +94,8 @@ |
347 | +@@ -62,6 +62,7 @@ |
348 | + #include "ibuf0ibuf.h" |
349 | + #include "srv0start.h" |
350 | + #include "srv0srv.h" |
351 | ++#include "xb0xb.h" |
352 | + #ifndef UNIV_HOTBACKUP |
353 | + # include "os0proc.h" |
354 | + # include "sync0sync.h" |
355 | +@@ -94,6 +95,8 @@ |
356 | /** Log sequence number at shutdown */ |
357 | UNIV_INTERN ib_uint64_t srv_shutdown_lsn; |
358 | |
359 | @@ -1095,7 +1112,7 @@ |
360 | #ifdef HAVE_DARWIN_THREADS |
361 | # include <sys/utsname.h> |
362 | /** TRUE if the F_FULLFSYNC option is available */ |
363 | -@@ -544,7 +546,7 @@ |
364 | +@@ -544,7 +547,7 @@ |
365 | /*********************************************************************//** |
366 | Creates or opens the log files and closes them. |
367 | @return DB_SUCCESS or error code */ |
368 | @@ -1104,7 +1121,7 @@ |
369 | ulint |
370 | open_or_create_log_file( |
371 | /*====================*/ |
372 | -@@ -702,7 +704,7 @@ |
373 | +@@ -702,7 +705,7 @@ |
374 | /*********************************************************************//** |
375 | Creates or opens database data files and closes them. |
376 | @return DB_SUCCESS or error code */ |
377 | @@ -1113,7 +1130,7 @@ |
378 | ulint |
379 | open_or_create_data_files( |
380 | /*======================*/ |
381 | -@@ -1359,7 +1361,7 @@ |
382 | +@@ -1359,7 +1362,7 @@ |
383 | } |
384 | #endif /* UNIV_LOG_ARCHIVE */ |
385 | |
386 | @@ -1122,7 +1139,7 @@ |
387 | fprintf(stderr, |
388 | "InnoDB: Error: combined size of log files" |
389 | " must be < 4 GB\n"); |
390 | -@@ -1601,6 +1603,10 @@ |
391 | +@@ -1601,6 +1604,10 @@ |
392 | are initialized in trx_sys_init_at_db_start(). */ |
393 | |
394 | recv_recovery_from_checkpoint_finish(); |
395 | @@ -1133,7 +1150,7 @@ |
396 | if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { |
397 | /* The following call is necessary for the insert |
398 | buffer to work with multiple tablespaces. We must |
399 | -@@ -1747,7 +1753,18 @@ |
400 | +@@ -1747,7 +1754,18 @@ |
401 | |
402 | if (srv_auto_extend_last_data_file |
403 | && sum_of_data_file_sizes < tablespace_size_in_header) { |
404 | @@ -1152,7 +1169,7 @@ |
405 | fprintf(stderr, |
406 | "InnoDB: Error: tablespace size stored in header" |
407 | " is %lu pages, but\n" |
408 | -@@ -1772,6 +1789,7 @@ |
409 | +@@ -1772,6 +1790,7 @@ |
410 | |
411 | return(DB_ERROR); |
412 | } |
413 | @@ -1160,7 +1177,18 @@ |
414 | } |
415 | |
416 | /* Check that os_fast_mutexes work as expected */ |
417 | -@@ -1867,6 +1885,7 @@ |
418 | +@@ -1793,6 +1812,10 @@ |
419 | + |
420 | + os_fast_mutex_free(&srv_os_test_mutex); |
421 | + |
422 | ++ if (srv_rebuild_indexes) { |
423 | ++ xb_compact_rebuild_indexes(); |
424 | ++ } |
425 | ++ |
426 | + if (srv_print_verbose_log) { |
427 | + ut_print_timestamp(stderr); |
428 | + fprintf(stderr, |
429 | +@@ -1867,6 +1890,7 @@ |
430 | ibuf_update_max_tablespace_id(); |
431 | } |
432 | |
433 | @@ -1251,3 +1279,38 @@ |
434 | } else { |
435 | fprintf(stderr, |
436 | "InnoDB: Since" |
437 | +--- a/storage/innodb_plugin/sync/sync0arr.c |
438 | ++++ b/storage/innodb_plugin/sync/sync0arr.c |
439 | +@@ -40,6 +40,7 @@ |
440 | + #include "os0sync.h" |
441 | + #include "os0file.h" |
442 | + #include "srv0srv.h" |
443 | ++#include "xb0xb.h" |
444 | + |
445 | + /* |
446 | + WAIT ARRAY |
447 | +@@ -927,6 +928,13 @@ |
448 | + ibool fatal = FALSE; |
449 | + double longest_diff = 0; |
450 | + |
451 | ++ if (srv_rebuild_indexes) { |
452 | ++ |
453 | ++ /* Avoid long semaphore warnings when rebuilding indexes */ |
454 | ++ |
455 | ++ return(FALSE); |
456 | ++ } |
457 | ++ |
458 | + for (i = 0; i < sync_primary_wait_array->n_cells; i++) { |
459 | + |
460 | + double diff; |
461 | +--- a/storage/innodb_plugin/include/buf0buf.h |
462 | ++++ b/storage/innodb_plugin/include/buf0buf.h |
463 | +@@ -1191,6 +1191,8 @@ |
464 | + frees a page in buffer pool */ |
465 | + # endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
466 | + #endif /* !UNIV_HOTBACKUP */ |
467 | ++ ibool is_compacted; /*!< TRUE if the page was skipped in |
468 | ++ compact backups */ |
469 | + }; |
470 | + |
471 | + /** The buffer control block structure */ |
472 | |
473 | === modified file 'patches/innodb55.patch' |
474 | --- patches/innodb55.patch 2012-02-22 16:37:18 +0000 |
475 | +++ patches/innodb55.patch 2013-01-14 11:06:22 +0000 |
476 | @@ -20,7 +20,15 @@ |
477 | /*===================*/ |
478 | --- a/storage/innobase/buf/buf0buf.c |
479 | +++ b/storage/innobase/buf/buf0buf.c |
480 | -@@ -518,7 +518,7 @@ |
481 | +@@ -51,6 +51,7 @@ |
482 | + #include "dict0dict.h" |
483 | + #include "log0recv.h" |
484 | + #include "page0zip.h" |
485 | ++#include "xb0xb.h" |
486 | + |
487 | + /* |
488 | + IMPLEMENTATION OF THE BUFFER POOL |
489 | +@@ -518,7 +519,7 @@ |
490 | return(TRUE); |
491 | } |
492 | |
493 | @@ -29,7 +37,15 @@ |
494 | if (recv_lsn_checks_on) { |
495 | ib_uint64_t current_lsn; |
496 | |
497 | -@@ -2299,7 +2299,8 @@ |
498 | +@@ -881,6 +882,7 @@ |
499 | + block->page.in_flush_list = FALSE; |
500 | + block->page.in_free_list = FALSE; |
501 | + block->page.in_LRU_list = FALSE; |
502 | ++ block->page.is_compacted = FALSE; |
503 | + block->in_unzip_LRU_list = FALSE; |
504 | + #endif /* UNIV_DEBUG */ |
505 | + #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG |
506 | +@@ -2299,7 +2301,8 @@ |
507 | ut_ad(zip_size == fil_space_get_zip_size(space)); |
508 | ut_ad(ut_is_2pow(zip_size)); |
509 | #ifndef UNIV_LOG_DEBUG |
510 | @@ -39,12 +55,27 @@ |
511 | || ibuf_page_low(space, zip_size, offset, |
512 | FALSE, file, line, NULL)); |
513 | #endif |
514 | -@@ -3668,7 +3669,7 @@ |
515 | +@@ -3567,6 +3570,13 @@ |
516 | + frame = ((buf_block_t*) bpage)->frame; |
517 | + } |
518 | + |
519 | ++ /* Do not validate, recover and apply change buffer entries to |
520 | ++ bogus pages which replace skipped pages in compact backups. */ |
521 | ++ if (srv_compact_backup && buf_page_is_compacted(frame)) { |
522 | ++ |
523 | ++ bpage->is_compacted = TRUE; |
524 | ++ } |
525 | ++ |
526 | + /* If this page is not uninitialized and not in the |
527 | + doublewrite buffer, then the page number and space id |
528 | + should be the same as in block. */ |
529 | +@@ -3668,7 +3678,8 @@ |
530 | recv_recover_page(TRUE, (buf_block_t*) bpage); |
531 | } |
532 | |
533 | - if (uncompressed && !recv_no_ibuf_operations) { |
534 | -+ if (uncompressed && !recv_no_ibuf_operations && !srv_fake_write) { |
535 | ++ if (uncompressed && !recv_no_ibuf_operations && |
536 | ++ !srv_fake_write && !bpage->is_compacted) { |
537 | ibuf_merge_or_delete_for_page( |
538 | (buf_block_t*) bpage, bpage->space, |
539 | bpage->offset, buf_page_get_zip_size(bpage), |
540 | @@ -695,7 +726,7 @@ |
541 | server_busy = log_sys->n_pending_checkpoint_writes |
542 | --- a/storage/innobase/log/log0recv.c |
543 | +++ b/storage/innobase/log/log0recv.c |
544 | -@@ -42,27 +42,27 @@ |
545 | +@@ -42,27 +42,28 @@ |
546 | #include "trx0undo.h" |
547 | #include "trx0rec.h" |
548 | #include "fil0fil.h" |
549 | @@ -709,6 +740,7 @@ |
550 | # include "sync0sync.h" |
551 | -#else /* !UNIV_HOTBACKUP */ |
552 | +//#else /* !UNIV_HOTBACKUP */ |
553 | ++#include "xb0xb.h" |
554 | |
555 | /** This is set to FALSE if the backup was originally taken with the |
556 | ibbackup --include regexp option: then we do not want to create tables in |
557 | @@ -727,7 +759,7 @@ |
558 | |
559 | /** The recovery system */ |
560 | UNIV_INTERN recv_sys_t* recv_sys = NULL; |
561 | -@@ -259,7 +259,7 @@ |
562 | +@@ -259,7 +260,7 @@ |
563 | { |
564 | recv_lsn_checks_on = FALSE; |
565 | |
566 | @@ -736,7 +768,7 @@ |
567 | |
568 | recv_recovery_on = FALSE; |
569 | |
570 | -@@ -285,7 +285,7 @@ |
571 | +@@ -285,7 +286,7 @@ |
572 | |
573 | recv_max_parsed_page_no = 0; |
574 | |
575 | @@ -745,7 +777,7 @@ |
576 | |
577 | recv_max_page_lsn = 0; |
578 | } |
579 | -@@ -623,7 +623,7 @@ |
580 | +@@ -623,7 +624,7 @@ |
581 | /***********************************************************************//** |
582 | Checks the consistency of the checkpoint info |
583 | @return TRUE if ok */ |
584 | @@ -754,7 +786,7 @@ |
585 | ibool |
586 | recv_check_cp_is_consistent( |
587 | /*========================*/ |
588 | -@@ -653,7 +653,7 @@ |
589 | +@@ -653,7 +654,7 @@ |
590 | /********************************************************//** |
591 | Looks for the maximum consistent checkpoint from the log groups. |
592 | @return error code or DB_SUCCESS */ |
593 | @@ -763,7 +795,7 @@ |
594 | ulint |
595 | recv_find_max_checkpoint( |
596 | /*=====================*/ |
597 | -@@ -828,7 +828,7 @@ |
598 | +@@ -828,7 +829,7 @@ |
599 | InnoDB-3.23.52 where the checksum field contains the log block number. |
600 | @return TRUE if ok, or if the log block may be in the format of InnoDB |
601 | version predating 3.23.52 */ |
602 | @@ -772,7 +804,7 @@ |
603 | ibool |
604 | log_block_checksum_is_ok_or_old_format( |
605 | /*===================================*/ |
606 | -@@ -1496,6 +1496,7 @@ |
607 | +@@ -1496,6 +1497,7 @@ |
608 | buf_block_get_page_no(block)); |
609 | |
610 | if ((recv_addr == NULL) |
611 | @@ -780,7 +812,25 @@ |
612 | || (recv_addr->state == RECV_BEING_PROCESSED) |
613 | || (recv_addr->state == RECV_PROCESSED)) { |
614 | |
615 | -@@ -2308,7 +2309,7 @@ |
616 | +@@ -1585,9 +1587,16 @@ |
617 | + if (page_zip) { |
618 | + memset(FIL_PAGE_LSN + page_zip->data, 0, 8); |
619 | + } |
620 | ++ |
621 | ++ if (block->page.is_compacted) { |
622 | ++ |
623 | ++ ut_ad(srv_compact_backup); |
624 | ++ |
625 | ++ block->page.is_compacted = FALSE; |
626 | ++ } |
627 | + } |
628 | + |
629 | +- if (recv->start_lsn >= page_lsn) { |
630 | ++ if (!block->page.is_compacted && recv->start_lsn >= page_lsn) { |
631 | + |
632 | + ib_uint64_t end_lsn; |
633 | + |
634 | +@@ -2308,7 +2317,7 @@ |
635 | || type == MLOG_FILE_RENAME |
636 | || type == MLOG_FILE_DELETE) { |
637 | ut_a(space); |
638 | @@ -789,7 +839,7 @@ |
639 | if (recv_replay_file_ops) { |
640 | |
641 | /* In ibbackup --apply-log, replay an .ibd file |
642 | -@@ -2331,7 +2332,7 @@ |
643 | +@@ -2331,7 +2340,7 @@ |
644 | ut_error; |
645 | } |
646 | } |
647 | @@ -798,7 +848,7 @@ |
648 | /* In normal mysqld crash recovery we do not try to |
649 | replay file operations */ |
650 | #ifdef UNIV_LOG_LSN_DEBUG |
651 | -@@ -2748,8 +2749,11 @@ |
652 | +@@ -2748,8 +2757,11 @@ |
653 | |
654 | fprintf(stderr, |
655 | "InnoDB: Doing recovery: scanned up to" |
656 | @@ -812,7 +862,7 @@ |
657 | } |
658 | } |
659 | |
660 | -@@ -2863,12 +2867,14 @@ |
661 | +@@ -2863,12 +2875,14 @@ |
662 | |
663 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
664 | |
665 | @@ -828,7 +878,7 @@ |
666 | } |
667 | } |
668 | |
669 | -@@ -3018,6 +3024,7 @@ |
670 | +@@ -3018,6 +3032,7 @@ |
671 | recv_sys->recovered_lsn = checkpoint_lsn; |
672 | |
673 | srv_start_lsn = checkpoint_lsn; |
674 | @@ -836,7 +886,7 @@ |
675 | } |
676 | |
677 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
678 | -@@ -3299,6 +3306,7 @@ |
679 | +@@ -3299,6 +3314,7 @@ |
680 | that the data dictionary tables will be free of any locks. |
681 | The data dictionary latch should guarantee that there is at |
682 | most one data dictionary transaction active at a time. */ |
683 | @@ -918,44 +968,6 @@ |
684 | +*/ |
685 | #endif |
686 | } |
687 | ---- a/storage/innobase/row/row0merge.c |
688 | -+++ b/storage/innobase/row/row0merge.c |
689 | -@@ -459,7 +459,9 @@ |
690 | - rec = rec_convert_dtuple_to_rec(*buf, index, tuple, n_ext); |
691 | - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); |
692 | - |
693 | -- innobase_rec_to_mysql(dup->table, rec, index, offsets); |
694 | -+ //innobase_rec_to_mysql(dup->table, rec, index, offsets); |
695 | -+ fprintf(stderr, "InnoDB: Error: row_merge_dup_report() is called.\n"); |
696 | -+ ut_error; |
697 | - |
698 | - mem_heap_free(heap); |
699 | - } |
700 | -@@ -1478,8 +1480,12 @@ |
701 | - case 0: |
702 | - if (UNIV_UNLIKELY |
703 | - (dict_index_is_unique(index) && !null_eq)) { |
704 | -- innobase_rec_to_mysql(table, mrec0, |
705 | -+ /* innobase_rec_to_mysql(table, mrec0, |
706 | - index, offsets0); |
707 | -+ */ |
708 | -+ (void) table; |
709 | -+ fprintf(stderr, "InnoDB: Error: row_merge_blocks() is called.\n"); |
710 | -+ ut_error; |
711 | - mem_heap_free(heap); |
712 | - return(DB_DUPLICATE_KEY); |
713 | - } |
714 | -@@ -2627,7 +2633,9 @@ |
715 | - |
716 | - /* Reset the MySQL row buffer that is used when reporting |
717 | - duplicate keys. */ |
718 | -- innobase_rec_reset(table); |
719 | -+ //innobase_rec_reset(table); |
720 | -+ fprintf(stderr, "InnoDB: Error: row_merge_build_indexes() is called.\n"); |
721 | -+ ut_error; |
722 | - |
723 | - /* Read clustered index of the table and create files for |
724 | - secondary index entries for merge sort */ |
725 | --- a/storage/innobase/srv/srv0srv.c |
726 | +++ b/storage/innobase/srv/srv0srv.c |
727 | @@ -399,6 +399,9 @@ |
728 | @@ -1004,7 +1016,15 @@ |
729 | if (trx->was_chosen_as_deadlock_victim) { |
730 | --- a/storage/innobase/srv/srv0start.c |
731 | +++ b/storage/innobase/srv/srv0start.c |
732 | -@@ -93,6 +93,8 @@ |
733 | +@@ -62,6 +62,7 @@ |
734 | + #include "ibuf0ibuf.h" |
735 | + #include "srv0start.h" |
736 | + #include "srv0srv.h" |
737 | ++#include "xb0xb.h" |
738 | + #ifndef UNIV_HOTBACKUP |
739 | + # include "os0proc.h" |
740 | + # include "sync0sync.h" |
741 | +@@ -93,6 +94,8 @@ |
742 | /** Log sequence number at shutdown */ |
743 | UNIV_INTERN ib_uint64_t srv_shutdown_lsn; |
744 | |
745 | @@ -1013,7 +1033,7 @@ |
746 | #ifdef HAVE_DARWIN_THREADS |
747 | # include <sys/utsname.h> |
748 | /** TRUE if the F_FULLFSYNC option is available */ |
749 | -@@ -548,7 +550,7 @@ |
750 | +@@ -548,7 +551,7 @@ |
751 | /*********************************************************************//** |
752 | Creates or opens the log files and closes them. |
753 | @return DB_SUCCESS or error code */ |
754 | @@ -1022,7 +1042,7 @@ |
755 | ulint |
756 | open_or_create_log_file( |
757 | /*====================*/ |
758 | -@@ -708,7 +710,7 @@ |
759 | +@@ -708,7 +711,7 @@ |
760 | /*********************************************************************//** |
761 | Creates or opens database data files and closes them. |
762 | @return DB_SUCCESS or error code */ |
763 | @@ -1031,7 +1051,7 @@ |
764 | ulint |
765 | open_or_create_data_files( |
766 | /*======================*/ |
767 | -@@ -1419,7 +1421,7 @@ |
768 | +@@ -1419,7 +1422,7 @@ |
769 | } |
770 | #endif /* UNIV_LOG_ARCHIVE */ |
771 | |
772 | @@ -1040,7 +1060,7 @@ |
773 | ut_print_timestamp(stderr); |
774 | fprintf(stderr, |
775 | " InnoDB: Error: combined size of log files" |
776 | -@@ -1714,6 +1716,10 @@ |
777 | +@@ -1714,6 +1717,10 @@ |
778 | are initialized in trx_sys_init_at_db_start(). */ |
779 | |
780 | recv_recovery_from_checkpoint_finish(); |
781 | @@ -1051,7 +1071,7 @@ |
782 | if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { |
783 | /* The following call is necessary for the insert |
784 | buffer to work with multiple tablespaces. We must |
785 | -@@ -1873,6 +1879,17 @@ |
786 | +@@ -1873,6 +1880,17 @@ |
787 | if (!srv_auto_extend_last_data_file |
788 | && sum_of_data_file_sizes != tablespace_size_in_header) { |
789 | |
790 | @@ -1069,7 +1089,7 @@ |
791 | ut_print_timestamp(stderr); |
792 | fprintf(stderr, |
793 | " InnoDB: Error: tablespace size" |
794 | -@@ -1952,6 +1969,7 @@ |
795 | +@@ -1952,6 +1970,7 @@ |
796 | |
797 | return(DB_ERROR); |
798 | } |
799 | @@ -1077,7 +1097,18 @@ |
800 | } |
801 | |
802 | /* Check that os_fast_mutexes work as expected */ |
803 | -@@ -2064,6 +2082,7 @@ |
804 | +@@ -1976,6 +1995,10 @@ |
805 | + |
806 | + os_fast_mutex_free(&srv_os_test_mutex); |
807 | + |
808 | ++ if (srv_rebuild_indexes) { |
809 | ++ xb_compact_rebuild_indexes(); |
810 | ++ } |
811 | ++ |
812 | + if (srv_print_verbose_log) { |
813 | + ut_print_timestamp(stderr); |
814 | + fprintf(stderr, |
815 | +@@ -2064,6 +2087,7 @@ |
816 | ibuf_update_max_tablespace_id(); |
817 | } |
818 | |
819 | @@ -1168,3 +1199,51 @@ |
820 | ut_a(purge_sys->trx->n_active_thrs == 0); |
821 | |
822 | rw_lock_x_lock(&purge_sys->latch); |
823 | +--- a/configure.cmake |
824 | ++++ b/configure.cmake |
825 | +@@ -149,7 +149,9 @@ |
826 | + SET(CMAKE_REQUIRED_LIBRARIES |
827 | + ${LIBM} ${LIBNSL} ${LIBBIND} ${LIBCRYPT} ${LIBSOCKET} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT} ${LIBRT}) |
828 | + |
829 | +- LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) |
830 | ++ IF(CMAKE_REQUIRED_LIBRARIES) |
831 | ++ LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) |
832 | ++ ENDIF() |
833 | + LINK_LIBRARIES(${CMAKE_THREAD_LIBS_INIT}) |
834 | + |
835 | + OPTION(WITH_LIBWRAP "Compile with tcp wrappers support" OFF) |
836 | +--- a/storage/innobase/sync/sync0arr.c |
837 | ++++ b/storage/innobase/sync/sync0arr.c |
838 | +@@ -41,6 +41,7 @@ |
839 | + #include "os0file.h" |
840 | + #include "srv0srv.h" |
841 | + #include "ha_prototypes.h" |
842 | ++#include "xb0xb.h" |
843 | + |
844 | + /* |
845 | + WAIT ARRAY |
846 | +@@ -928,6 +929,13 @@ |
847 | + ibool fatal = FALSE; |
848 | + double longest_diff = 0; |
849 | + |
850 | ++ if (srv_rebuild_indexes) { |
851 | ++ |
852 | ++ /* Avoid long semaphore warnings when rebuilding indexes */ |
853 | ++ |
854 | ++ return(FALSE); |
855 | ++ } |
856 | ++ |
857 | + #ifdef UNIV_DEBUG_VALGRIND |
858 | + /* Increase the timeouts if running under valgrind because it executes |
859 | + extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that |
860 | +--- a/storage/innobase/include/buf0buf.h |
861 | ++++ b/storage/innobase/include/buf0buf.h |
862 | +@@ -1441,6 +1441,8 @@ |
863 | + frees a page in buffer pool */ |
864 | + # endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
865 | + #endif /* !UNIV_HOTBACKUP */ |
866 | ++ ibool is_compacted; /*!< TRUE if the page was skipped in |
867 | ++ compact backups */ |
868 | + }; |
869 | + |
870 | + /** The buffer control block structure */ |
871 | |
872 | === modified file 'patches/xtradb51.patch' |
873 | --- patches/xtradb51.patch 2012-02-22 16:37:18 +0000 |
874 | +++ patches/xtradb51.patch 2013-01-14 11:06:22 +0000 |
875 | @@ -20,7 +20,15 @@ |
876 | /*===================*/ |
877 | --- a/storage/innodb_plugin/buf/buf0buf.c |
878 | +++ b/storage/innodb_plugin/buf/buf0buf.c |
879 | -@@ -412,7 +412,7 @@ |
880 | +@@ -53,6 +53,7 @@ |
881 | + #include "page0zip.h" |
882 | + #include "trx0trx.h" |
883 | + #include "srv0start.h" |
884 | ++#include "xb0xb.h" |
885 | + |
886 | + /* prototypes for new functions added to ha_innodb.cc */ |
887 | + trx_t* innobase_get_trx(); |
888 | +@@ -412,7 +413,7 @@ |
889 | return(TRUE); |
890 | } |
891 | |
892 | @@ -29,7 +37,15 @@ |
893 | if (recv_lsn_checks_on) { |
894 | ib_uint64_t current_lsn; |
895 | |
896 | -@@ -1888,7 +1888,9 @@ |
897 | +@@ -744,6 +745,7 @@ |
898 | + block->page.zip_list.prev = NULL; |
899 | + block->page.zip_list.next = NULL; |
900 | + block->page.in_LRU_list = FALSE; |
901 | ++ block->page.is_compacted = FALSE; |
902 | + block->in_unzip_LRU_list = FALSE; |
903 | + #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG |
904 | + block->n_pointers = 0; |
905 | +@@ -1888,7 +1890,9 @@ |
906 | ut_ad(zip_size == fil_space_get_zip_size(space)); |
907 | ut_ad(ut_is_2pow(zip_size)); |
908 | #ifndef UNIV_LOG_DEBUG |
909 | @@ -40,12 +56,27 @@ |
910 | #endif |
911 | if (innobase_get_slow_log()) { |
912 | trx = innobase_get_trx(); |
913 | -@@ -3302,7 +3304,7 @@ |
914 | +@@ -3190,6 +3194,13 @@ |
915 | + frame = ((buf_block_t*) bpage)->frame; |
916 | + } |
917 | + |
918 | ++ /* Do not validate, recover and apply change buffer entries to |
919 | ++ bogus pages which replace skipped pages in compact backups. */ |
920 | ++ if (srv_compact_backup && buf_page_is_compacted(frame)) { |
921 | ++ |
922 | ++ bpage->is_compacted = TRUE; |
923 | ++ } |
924 | ++ |
925 | + /* If this page is not uninitialized and not in the |
926 | + doublewrite buffer, then the page number and space id |
927 | + should be the same as in block. */ |
928 | +@@ -3302,7 +3313,8 @@ |
929 | recv_recover_page(TRUE, (buf_block_t*) bpage); |
930 | } |
931 | |
932 | - if (uncompressed && !recv_no_ibuf_operations) { |
933 | -+ if (uncompressed && !recv_no_ibuf_operations && !srv_fake_write) { |
934 | ++ if (uncompressed && !recv_no_ibuf_operations && |
935 | ++ !srv_fake_write && !bpage->is_compacted) { |
936 | ibuf_merge_or_delete_for_page( |
937 | /* Delete possible entries, if bpage is_corrupt */ |
938 | (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL : |
939 | @@ -723,7 +754,7 @@ |
940 | /* In this fastest shutdown we do not flush the buffer pool: |
941 | --- a/storage/innodb_plugin/log/log0recv.c |
942 | +++ b/storage/innodb_plugin/log/log0recv.c |
943 | -@@ -42,27 +42,27 @@ |
944 | +@@ -42,27 +42,28 @@ |
945 | #include "trx0undo.h" |
946 | #include "trx0rec.h" |
947 | #include "fil0fil.h" |
948 | @@ -737,6 +768,7 @@ |
949 | # include "sync0sync.h" |
950 | -#else /* !UNIV_HOTBACKUP */ |
951 | +//#else /* !UNIV_HOTBACKUP */ |
952 | ++#include "xb0xb.h" |
953 | |
954 | /** This is set to FALSE if the backup was originally taken with the |
955 | ibbackup --include regexp option: then we do not want to create tables in |
956 | @@ -755,7 +787,7 @@ |
957 | |
958 | /** The recovery system */ |
959 | UNIV_INTERN recv_sys_t* recv_sys = NULL; |
960 | -@@ -621,7 +621,7 @@ |
961 | +@@ -621,7 +622,7 @@ |
962 | /***********************************************************************//** |
963 | Checks the consistency of the checkpoint info |
964 | @return TRUE if ok */ |
965 | @@ -764,7 +796,7 @@ |
966 | ibool |
967 | recv_check_cp_is_consistent( |
968 | /*========================*/ |
969 | -@@ -651,7 +651,7 @@ |
970 | +@@ -651,7 +652,7 @@ |
971 | /********************************************************//** |
972 | Looks for the maximum consistent checkpoint from the log groups. |
973 | @return error code or DB_SUCCESS */ |
974 | @@ -773,7 +805,7 @@ |
975 | ulint |
976 | recv_find_max_checkpoint( |
977 | /*=====================*/ |
978 | -@@ -840,7 +840,7 @@ |
979 | +@@ -840,7 +841,7 @@ |
980 | InnoDB-3.23.52 where the checksum field contains the log block number. |
981 | @return TRUE if ok, or if the log block may be in the format of InnoDB |
982 | version predating 3.23.52 */ |
983 | @@ -782,7 +814,25 @@ |
984 | ibool |
985 | log_block_checksum_is_ok_or_old_format( |
986 | /*===================================*/ |
987 | -@@ -2369,7 +2369,7 @@ |
988 | +@@ -1629,9 +1630,16 @@ |
989 | + if (page_zip) { |
990 | + memset(FIL_PAGE_LSN + page_zip->data, 0, 8); |
991 | + } |
992 | ++ |
993 | ++ if (block->page.is_compacted) { |
994 | ++ |
995 | ++ ut_ad(srv_compact_backup); |
996 | ++ |
997 | ++ block->page.is_compacted = FALSE; |
998 | ++ } |
999 | + } |
1000 | + |
1001 | +- if (recv->start_lsn >= page_lsn) { |
1002 | ++ if (!block->page.is_compacted && recv->start_lsn >= page_lsn) { |
1003 | + |
1004 | + ib_uint64_t end_lsn; |
1005 | + |
1006 | +@@ -2369,7 +2377,7 @@ |
1007 | || type == MLOG_FILE_RENAME |
1008 | || type == MLOG_FILE_DELETE) { |
1009 | ut_a(space); |
1010 | @@ -791,7 +841,7 @@ |
1011 | if (recv_replay_file_ops) { |
1012 | |
1013 | /* In ibbackup --apply-log, replay an .ibd file |
1014 | -@@ -2392,7 +2392,7 @@ |
1015 | +@@ -2392,7 +2400,7 @@ |
1016 | ut_error; |
1017 | } |
1018 | } |
1019 | @@ -800,7 +850,7 @@ |
1020 | /* In normal mysqld crash recovery we do not try to |
1021 | replay file operations */ |
1022 | #ifdef UNIV_LOG_LSN_DEBUG |
1023 | -@@ -2809,8 +2809,11 @@ |
1024 | +@@ -2809,8 +2817,11 @@ |
1025 | |
1026 | fprintf(stderr, |
1027 | "InnoDB: Doing recovery: scanned up to" |
1028 | @@ -814,7 +864,7 @@ |
1029 | } |
1030 | } |
1031 | |
1032 | -@@ -2922,12 +2925,14 @@ |
1033 | +@@ -2922,12 +2933,14 @@ |
1034 | |
1035 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
1036 | |
1037 | @@ -830,7 +880,7 @@ |
1038 | } |
1039 | } |
1040 | |
1041 | -@@ -3095,6 +3100,7 @@ |
1042 | +@@ -3095,6 +3108,7 @@ |
1043 | recv_sys->recovered_lsn = checkpoint_lsn; |
1044 | |
1045 | srv_start_lsn = checkpoint_lsn; |
1046 | @@ -838,7 +888,7 @@ |
1047 | } |
1048 | |
1049 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
1050 | -@@ -3453,6 +3459,7 @@ |
1051 | +@@ -3453,6 +3467,7 @@ |
1052 | that the data dictionary tables will be free of any locks. |
1053 | The data dictionary latch should guarantee that there is at |
1054 | most one data dictionary transaction active at a time. */ |
1055 | @@ -921,44 +971,6 @@ |
1056 | #endif |
1057 | } |
1058 | |
1059 | ---- a/storage/innodb_plugin/row/row0merge.c |
1060 | -+++ b/storage/innodb_plugin/row/row0merge.c |
1061 | -@@ -454,7 +454,9 @@ |
1062 | - rec = rec_convert_dtuple_to_rec(*buf, index, tuple, n_ext); |
1063 | - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); |
1064 | - |
1065 | -- innobase_rec_to_mysql(dup->table, rec, index, offsets); |
1066 | -+ //innobase_rec_to_mysql(dup->table, rec, index, offsets); |
1067 | -+ fprintf(stderr, "InnoDB: Error: row_merge_dup_report() is called.\n"); |
1068 | -+ ut_error; |
1069 | - |
1070 | - mem_heap_free(heap); |
1071 | - } |
1072 | -@@ -1465,8 +1467,11 @@ |
1073 | - case 0: |
1074 | - if (UNIV_UNLIKELY |
1075 | - (dict_index_is_unique(index) && !null_eq)) { |
1076 | -- innobase_rec_to_mysql(table, mrec0, |
1077 | -- index, offsets0); |
1078 | -+ //innobase_rec_to_mysql(table, mrec0, |
1079 | -+ // index, offsets0); |
1080 | -+ (void) table; |
1081 | -+ fprintf(stderr, "InnoDB: Error: row_merge_blocks() is called.\n"); |
1082 | -+ ut_error; |
1083 | - mem_heap_free(heap); |
1084 | - return(DB_DUPLICATE_KEY); |
1085 | - } |
1086 | -@@ -2594,7 +2599,9 @@ |
1087 | - |
1088 | - /* Reset the MySQL row buffer that is used when reporting |
1089 | - duplicate keys. */ |
1090 | -- innobase_rec_reset(table); |
1091 | -+ //innobase_rec_reset(table); |
1092 | -+ fprintf(stderr, "InnoDB: Error: row_merge_build_indexes() is called.\n"); |
1093 | -+ ut_error; |
1094 | - |
1095 | - /* Read clustered index of the table and create files for |
1096 | - secondary index entries for merge sort */ |
1097 | --- a/storage/innodb_plugin/srv/srv0srv.c |
1098 | +++ b/storage/innodb_plugin/srv/srv0srv.c |
1099 | @@ -86,11 +86,6 @@ |
1100 | @@ -1048,7 +1060,15 @@ |
1101 | |
1102 | --- a/storage/innodb_plugin/srv/srv0start.c |
1103 | +++ b/storage/innodb_plugin/srv/srv0start.c |
1104 | -@@ -95,6 +95,8 @@ |
1105 | +@@ -62,6 +62,7 @@ |
1106 | + #include "ibuf0ibuf.h" |
1107 | + #include "srv0start.h" |
1108 | + #include "srv0srv.h" |
1109 | ++#include "xb0xb.h" |
1110 | + #ifndef UNIV_HOTBACKUP |
1111 | + # include "os0proc.h" |
1112 | + # include "sync0sync.h" |
1113 | +@@ -95,6 +96,8 @@ |
1114 | /** Log sequence number at shutdown */ |
1115 | UNIV_INTERN ib_uint64_t srv_shutdown_lsn; |
1116 | |
1117 | @@ -1057,7 +1077,7 @@ |
1118 | #ifdef HAVE_DARWIN_THREADS |
1119 | # include <sys/utsname.h> |
1120 | /** TRUE if the F_FULLFSYNC option is available */ |
1121 | -@@ -545,7 +547,7 @@ |
1122 | +@@ -545,7 +548,7 @@ |
1123 | /*********************************************************************//** |
1124 | Creates or opens the log files and closes them. |
1125 | @return DB_SUCCESS or error code */ |
1126 | @@ -1066,7 +1086,7 @@ |
1127 | ulint |
1128 | open_or_create_log_file( |
1129 | /*====================*/ |
1130 | -@@ -703,7 +705,7 @@ |
1131 | +@@ -703,7 +706,7 @@ |
1132 | /*********************************************************************//** |
1133 | Creates or opens database data files and closes them. |
1134 | @return DB_SUCCESS or error code */ |
1135 | @@ -1075,7 +1095,7 @@ |
1136 | ulint |
1137 | open_or_create_data_files( |
1138 | /*======================*/ |
1139 | -@@ -1782,6 +1784,10 @@ |
1140 | +@@ -1782,6 +1785,10 @@ |
1141 | are initialized in trx_sys_init_at_db_start(). */ |
1142 | |
1143 | recv_recovery_from_checkpoint_finish(); |
1144 | @@ -1086,7 +1106,7 @@ |
1145 | if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { |
1146 | /* The following call is necessary for the insert |
1147 | buffer to work with multiple tablespaces. We must |
1148 | -@@ -1962,7 +1968,18 @@ |
1149 | +@@ -1962,7 +1969,18 @@ |
1150 | |
1151 | if (srv_auto_extend_last_data_file |
1152 | && sum_of_data_file_sizes < tablespace_size_in_header) { |
1153 | @@ -1105,7 +1125,7 @@ |
1154 | fprintf(stderr, |
1155 | "InnoDB: Error: tablespace size stored in header" |
1156 | " is %lu pages, but\n" |
1157 | -@@ -1987,6 +2004,7 @@ |
1158 | +@@ -1987,6 +2005,7 @@ |
1159 | |
1160 | return(DB_ERROR); |
1161 | } |
1162 | @@ -1113,7 +1133,18 @@ |
1163 | } |
1164 | |
1165 | /* Check that os_fast_mutexes work as expected */ |
1166 | -@@ -2089,6 +2107,7 @@ |
1167 | +@@ -2008,6 +2027,10 @@ |
1168 | + |
1169 | + os_fast_mutex_free(&srv_os_test_mutex); |
1170 | + |
1171 | ++ if (srv_rebuild_indexes) { |
1172 | ++ xb_compact_rebuild_indexes(); |
1173 | ++ } |
1174 | ++ |
1175 | + if (!srv_file_per_table_original_value |
1176 | + && srv_pass_corrupt_table) { |
1177 | + fprintf(stderr, "InnoDB: Warning:" |
1178 | +@@ -2089,6 +2112,7 @@ |
1179 | ibuf_update_max_tablespace_id(); |
1180 | } |
1181 | |
1182 | @@ -1334,3 +1365,38 @@ |
1183 | |
1184 | /* Write the log but do not flush it to disk */ |
1185 | |
1186 | +--- a/storage/innodb_plugin/sync/sync0arr.c |
1187 | ++++ b/storage/innodb_plugin/sync/sync0arr.c |
1188 | +@@ -40,6 +40,7 @@ |
1189 | + #include "os0sync.h" |
1190 | + #include "os0file.h" |
1191 | + #include "srv0srv.h" |
1192 | ++#include "xb0xb.h" |
1193 | + |
1194 | + /* |
1195 | + WAIT ARRAY |
1196 | +@@ -926,6 +927,13 @@ |
1197 | + ibool fatal = FALSE; |
1198 | + double longest_diff = 0; |
1199 | + |
1200 | ++ if (srv_rebuild_indexes) { |
1201 | ++ |
1202 | ++ /* Avoid long semaphore warnings when rebuilding indexes */ |
1203 | ++ |
1204 | ++ return(FALSE); |
1205 | ++ } |
1206 | ++ |
1207 | + for (i = 0; i < sync_primary_wait_array->n_cells; i++) { |
1208 | + |
1209 | + double diff; |
1210 | +--- a/storage/innodb_plugin/include/buf0buf.h |
1211 | ++++ b/storage/innodb_plugin/include/buf0buf.h |
1212 | +@@ -1211,6 +1211,8 @@ |
1213 | + frees a page in buffer pool */ |
1214 | + # endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
1215 | + #endif /* !UNIV_HOTBACKUP */ |
1216 | ++ ibool is_compacted; /*!< TRUE if the page was skipped in |
1217 | ++ compact backups */ |
1218 | + }; |
1219 | + |
1220 | + /** The buffer control block structure */ |
1221 | |
1222 | === modified file 'patches/xtradb55.patch' |
1223 | --- patches/xtradb55.patch 2012-02-22 16:37:18 +0000 |
1224 | +++ patches/xtradb55.patch 2013-01-14 11:06:22 +0000 |
1225 | @@ -20,7 +20,15 @@ |
1226 | /*===================*/ |
1227 | --- a/storage/innobase/buf/buf0buf.c |
1228 | +++ b/storage/innobase/buf/buf0buf.c |
1229 | -@@ -581,7 +581,7 @@ |
1230 | +@@ -53,6 +53,7 @@ |
1231 | + #include "page0zip.h" |
1232 | + #include "trx0trx.h" |
1233 | + #include "srv0start.h" |
1234 | ++#include "xb0xb.h" |
1235 | + |
1236 | + /* prototypes for new functions added to ha_innodb.cc */ |
1237 | + trx_t* innobase_get_trx(); |
1238 | +@@ -581,7 +582,7 @@ |
1239 | return(TRUE); |
1240 | } |
1241 | |
1242 | @@ -29,7 +37,15 @@ |
1243 | if (recv_lsn_checks_on) { |
1244 | ib_uint64_t current_lsn; |
1245 | |
1246 | -@@ -2542,7 +2542,8 @@ |
1247 | +@@ -965,6 +966,7 @@ |
1248 | + block->page.zip_list.prev = NULL; |
1249 | + block->page.zip_list.next = NULL; |
1250 | + block->page.in_LRU_list = FALSE; |
1251 | ++ block->page.is_compacted = FALSE; |
1252 | + block->in_unzip_LRU_list = FALSE; |
1253 | + #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG |
1254 | + block->n_pointers = 0; |
1255 | +@@ -2542,7 +2544,8 @@ |
1256 | ut_ad(zip_size == fil_space_get_zip_size(space)); |
1257 | ut_ad(ut_is_2pow(zip_size)); |
1258 | #ifndef UNIV_LOG_DEBUG |
1259 | @@ -39,12 +55,27 @@ |
1260 | || ibuf_page_low(space, zip_size, offset, |
1261 | FALSE, file, line, NULL)); |
1262 | #endif |
1263 | -@@ -4064,7 +4065,7 @@ |
1264 | +@@ -3952,6 +3955,13 @@ |
1265 | + frame = ((buf_block_t*) bpage)->frame; |
1266 | + } |
1267 | + |
1268 | ++ /* Do not validate, recover and apply change buffer entries to |
1269 | ++ bogus pages which replace skipped pages in compact backups. */ |
1270 | ++ if (srv_compact_backup && buf_page_is_compacted(frame)) { |
1271 | ++ |
1272 | ++ bpage->is_compacted = TRUE; |
1273 | ++ } |
1274 | ++ |
1275 | + /* If this page is not uninitialized and not in the |
1276 | + doublewrite buffer, then the page number and space id |
1277 | + should be the same as in block. */ |
1278 | +@@ -4064,7 +4074,8 @@ |
1279 | recv_recover_page(TRUE, (buf_block_t*) bpage); |
1280 | } |
1281 | |
1282 | - if (uncompressed && !recv_no_ibuf_operations) { |
1283 | -+ if (uncompressed && !recv_no_ibuf_operations && !srv_fake_write) { |
1284 | ++ if (uncompressed && !recv_no_ibuf_operations && |
1285 | ++ !srv_fake_write && !bpage->is_compacted) { |
1286 | ibuf_merge_or_delete_for_page( |
1287 | /* Delete possible entries, if bpage is_corrupt */ |
1288 | (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL : |
1289 | @@ -687,7 +718,7 @@ |
1290 | server_busy = log_sys->n_pending_checkpoint_writes |
1291 | --- a/storage/innobase/log/log0recv.c |
1292 | +++ b/storage/innobase/log/log0recv.c |
1293 | -@@ -42,27 +42,27 @@ |
1294 | +@@ -42,27 +42,28 @@ |
1295 | #include "trx0undo.h" |
1296 | #include "trx0rec.h" |
1297 | #include "fil0fil.h" |
1298 | @@ -701,6 +732,7 @@ |
1299 | # include "sync0sync.h" |
1300 | -#else /* !UNIV_HOTBACKUP */ |
1301 | +//#else /* !UNIV_HOTBACKUP */ |
1302 | ++#include "xb0xb.h" |
1303 | |
1304 | /** This is set to FALSE if the backup was originally taken with the |
1305 | ibbackup --include regexp option: then we do not want to create tables in |
1306 | @@ -719,7 +751,7 @@ |
1307 | |
1308 | /** The recovery system */ |
1309 | UNIV_INTERN recv_sys_t* recv_sys = NULL; |
1310 | -@@ -631,7 +631,7 @@ |
1311 | +@@ -631,7 +632,7 @@ |
1312 | /***********************************************************************//** |
1313 | Checks the consistency of the checkpoint info |
1314 | @return TRUE if ok */ |
1315 | @@ -728,7 +760,7 @@ |
1316 | ibool |
1317 | recv_check_cp_is_consistent( |
1318 | /*========================*/ |
1319 | -@@ -661,7 +661,7 @@ |
1320 | +@@ -661,7 +662,7 @@ |
1321 | /********************************************************//** |
1322 | Looks for the maximum consistent checkpoint from the log groups. |
1323 | @return error code or DB_SUCCESS */ |
1324 | @@ -737,7 +769,7 @@ |
1325 | ulint |
1326 | recv_find_max_checkpoint( |
1327 | /*=====================*/ |
1328 | -@@ -850,7 +850,7 @@ |
1329 | +@@ -850,7 +851,7 @@ |
1330 | InnoDB-3.23.52 where the checksum field contains the log block number. |
1331 | @return TRUE if ok, or if the log block may be in the format of InnoDB |
1332 | version predating 3.23.52 */ |
1333 | @@ -746,7 +778,25 @@ |
1334 | ibool |
1335 | log_block_checksum_is_ok_or_old_format( |
1336 | /*===================================*/ |
1337 | -@@ -2380,7 +2380,7 @@ |
1338 | +@@ -1639,9 +1640,16 @@ |
1339 | + if (page_zip) { |
1340 | + memset(FIL_PAGE_LSN + page_zip->data, 0, 8); |
1341 | + } |
1342 | ++ |
1343 | ++ if (block->page.is_compacted) { |
1344 | ++ |
1345 | ++ ut_ad(srv_compact_backup); |
1346 | ++ |
1347 | ++ block->page.is_compacted = FALSE; |
1348 | ++ } |
1349 | + } |
1350 | + |
1351 | +- if (recv->start_lsn >= page_lsn) { |
1352 | ++ if (!block->page.is_compacted && recv->start_lsn >= page_lsn) { |
1353 | + |
1354 | + ib_uint64_t end_lsn; |
1355 | + |
1356 | +@@ -2380,7 +2388,7 @@ |
1357 | || type == MLOG_FILE_RENAME |
1358 | || type == MLOG_FILE_DELETE) { |
1359 | ut_a(space); |
1360 | @@ -755,7 +805,7 @@ |
1361 | if (recv_replay_file_ops) { |
1362 | |
1363 | /* In ibbackup --apply-log, replay an .ibd file |
1364 | -@@ -2403,7 +2403,7 @@ |
1365 | +@@ -2403,7 +2411,7 @@ |
1366 | ut_error; |
1367 | } |
1368 | } |
1369 | @@ -764,7 +814,7 @@ |
1370 | /* In normal mysqld crash recovery we do not try to |
1371 | replay file operations */ |
1372 | #ifdef UNIV_LOG_LSN_DEBUG |
1373 | -@@ -2820,8 +2820,11 @@ |
1374 | +@@ -2820,8 +2828,11 @@ |
1375 | |
1376 | fprintf(stderr, |
1377 | "InnoDB: Doing recovery: scanned up to" |
1378 | @@ -778,7 +828,7 @@ |
1379 | } |
1380 | } |
1381 | |
1382 | -@@ -2935,12 +2938,14 @@ |
1383 | +@@ -2935,12 +2946,14 @@ |
1384 | |
1385 | if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { |
1386 | |
1387 | @@ -794,7 +844,7 @@ |
1388 | } |
1389 | } |
1390 | |
1391 | -@@ -3109,6 +3114,7 @@ |
1392 | +@@ -3109,6 +3122,7 @@ |
1393 | recv_sys->recovered_lsn = checkpoint_lsn; |
1394 | |
1395 | srv_start_lsn = checkpoint_lsn; |
1396 | @@ -802,7 +852,7 @@ |
1397 | } |
1398 | |
1399 | contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn, |
1400 | -@@ -3474,6 +3480,7 @@ |
1401 | +@@ -3474,6 +3488,7 @@ |
1402 | that the data dictionary tables will be free of any locks. |
1403 | The data dictionary latch should guarantee that there is at |
1404 | most one data dictionary transaction active at a time. */ |
1405 | @@ -902,44 +952,6 @@ |
1406 | +*/ |
1407 | #endif |
1408 | } |
1409 | ---- a/storage/innobase/row/row0merge.c |
1410 | -+++ b/storage/innobase/row/row0merge.c |
1411 | -@@ -460,7 +460,9 @@ |
1412 | - rec = rec_convert_dtuple_to_rec(*buf, index, tuple, n_ext); |
1413 | - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); |
1414 | - |
1415 | -- innobase_rec_to_mysql(dup->table, rec, index, offsets); |
1416 | -+ //innobase_rec_to_mysql(dup->table, rec, index, offsets); |
1417 | -+ fprintf(stderr, "InnoDB: Error: row_merge_dup_report() is called.\n"); |
1418 | -+ ut_error; |
1419 | - |
1420 | - mem_heap_free(heap); |
1421 | - } |
1422 | -@@ -1486,8 +1488,11 @@ |
1423 | - case 0: |
1424 | - if (UNIV_UNLIKELY |
1425 | - (dict_index_is_unique(index) && !null_eq)) { |
1426 | -- innobase_rec_to_mysql(table, mrec0, |
1427 | -- index, offsets0); |
1428 | -+ //innobase_rec_to_mysql(table, mrec0, |
1429 | -+ // index, offsets0); |
1430 | -+ (void) table; |
1431 | -+ fprintf(stderr, "InnoDB: Error: row_merge_blocks() is called.\n"); |
1432 | -+ ut_error; |
1433 | - mem_heap_free(heap); |
1434 | - return(DB_DUPLICATE_KEY); |
1435 | - } |
1436 | -@@ -2636,7 +2641,9 @@ |
1437 | - |
1438 | - /* Reset the MySQL row buffer that is used when reporting |
1439 | - duplicate keys. */ |
1440 | -- innobase_rec_reset(table); |
1441 | -+ //innobase_rec_reset(table); |
1442 | -+ fprintf(stderr, "InnoDB: Error: row_merge_build_indexes() is called.\n"); |
1443 | -+ ut_error; |
1444 | - |
1445 | - /* Read clustered index of the table and create files for |
1446 | - secondary index entries for merge sort */ |
1447 | --- a/storage/innobase/srv/srv0srv.c |
1448 | +++ b/storage/innobase/srv/srv0srv.c |
1449 | @@ -87,11 +87,6 @@ |
1450 | @@ -1048,7 +1060,15 @@ |
1451 | |
1452 | --- a/storage/innobase/srv/srv0start.c |
1453 | +++ b/storage/innobase/srv/srv0start.c |
1454 | -@@ -94,6 +94,8 @@ |
1455 | +@@ -62,6 +62,7 @@ |
1456 | + #include "ibuf0ibuf.h" |
1457 | + #include "srv0start.h" |
1458 | + #include "srv0srv.h" |
1459 | ++#include "xb0xb.h" |
1460 | + #ifndef UNIV_HOTBACKUP |
1461 | + # include "os0proc.h" |
1462 | + # include "sync0sync.h" |
1463 | +@@ -94,6 +95,8 @@ |
1464 | /** Log sequence number at shutdown */ |
1465 | UNIV_INTERN ib_uint64_t srv_shutdown_lsn; |
1466 | |
1467 | @@ -1057,7 +1077,7 @@ |
1468 | #ifdef HAVE_DARWIN_THREADS |
1469 | # include <sys/utsname.h> |
1470 | /** TRUE if the F_FULLFSYNC option is available */ |
1471 | -@@ -549,7 +551,7 @@ |
1472 | +@@ -549,7 +552,7 @@ |
1473 | /*********************************************************************//** |
1474 | Creates or opens the log files and closes them. |
1475 | @return DB_SUCCESS or error code */ |
1476 | @@ -1066,7 +1086,7 @@ |
1477 | ulint |
1478 | open_or_create_log_file( |
1479 | /*====================*/ |
1480 | -@@ -709,7 +711,7 @@ |
1481 | +@@ -709,7 +712,7 @@ |
1482 | /*********************************************************************//** |
1483 | Creates or opens database data files and closes them. |
1484 | @return DB_SUCCESS or error code */ |
1485 | @@ -1075,7 +1095,7 @@ |
1486 | ulint |
1487 | open_or_create_data_files( |
1488 | /*======================*/ |
1489 | -@@ -1875,6 +1877,10 @@ |
1490 | +@@ -1875,6 +1878,10 @@ |
1491 | are initialized in trx_sys_init_at_db_start(). */ |
1492 | |
1493 | recv_recovery_from_checkpoint_finish(); |
1494 | @@ -1086,7 +1106,7 @@ |
1495 | if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { |
1496 | /* The following call is necessary for the insert |
1497 | buffer to work with multiple tablespaces. We must |
1498 | -@@ -2054,6 +2060,17 @@ |
1499 | +@@ -2054,6 +2061,17 @@ |
1500 | if (!srv_auto_extend_last_data_file |
1501 | && sum_of_data_file_sizes != tablespace_size_in_header) { |
1502 | |
1503 | @@ -1104,7 +1124,7 @@ |
1504 | ut_print_timestamp(stderr); |
1505 | fprintf(stderr, |
1506 | " InnoDB: Error: tablespace size" |
1507 | -@@ -2133,6 +2150,7 @@ |
1508 | +@@ -2133,6 +2151,7 @@ |
1509 | |
1510 | return(DB_ERROR); |
1511 | } |
1512 | @@ -1112,7 +1132,18 @@ |
1513 | } |
1514 | |
1515 | /* Check that os_fast_mutexes work as expected */ |
1516 | -@@ -2252,6 +2270,7 @@ |
1517 | +@@ -2157,6 +2176,10 @@ |
1518 | + |
1519 | + os_fast_mutex_free(&srv_os_test_mutex); |
1520 | + |
1521 | ++ if (srv_rebuild_indexes) { |
1522 | ++ xb_compact_rebuild_indexes(); |
1523 | ++ } |
1524 | ++ |
1525 | + if (!srv_file_per_table_original_value |
1526 | + && srv_pass_corrupt_table) { |
1527 | + fprintf(stderr, "InnoDB: Warning:" |
1528 | +@@ -2252,6 +2275,7 @@ |
1529 | ibuf_update_max_tablespace_id(); |
1530 | } |
1531 | |
1532 | @@ -1315,3 +1346,51 @@ |
1533 | |
1534 | /* Write the log but do not flush it to disk */ |
1535 | |
1536 | +--- a/configure.cmake |
1537 | ++++ b/configure.cmake |
1538 | +@@ -149,7 +149,9 @@ |
1539 | + SET(CMAKE_REQUIRED_LIBRARIES |
1540 | + ${LIBM} ${LIBNSL} ${LIBBIND} ${LIBCRYPT} ${LIBSOCKET} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT} ${LIBRT}) |
1541 | + |
1542 | +- LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) |
1543 | ++ IF(CMAKE_REQUIRED_LIBRARIES) |
1544 | ++ LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) |
1545 | ++ ENDIF() |
1546 | + LINK_LIBRARIES(${CMAKE_THREAD_LIBS_INIT}) |
1547 | + |
1548 | + OPTION(WITH_LIBWRAP "Compile with tcp wrappers support" OFF) |
1549 | +--- a/storage/innobase/sync/sync0arr.c |
1550 | ++++ b/storage/innobase/sync/sync0arr.c |
1551 | +@@ -41,6 +41,7 @@ |
1552 | + #include "os0file.h" |
1553 | + #include "srv0srv.h" |
1554 | + #include "ha_prototypes.h" |
1555 | ++#include "xb0xb.h" |
1556 | + |
1557 | + /* |
1558 | + WAIT ARRAY |
1559 | +@@ -926,6 +927,13 @@ |
1560 | + ibool fatal = FALSE; |
1561 | + double longest_diff = 0; |
1562 | + |
1563 | ++ if (srv_rebuild_indexes) { |
1564 | ++ |
1565 | ++ /* Avoid long semaphore warnings when rebuilding indexes */ |
1566 | ++ |
1567 | ++ return(FALSE); |
1568 | ++ } |
1569 | ++ |
1570 | + #ifdef UNIV_DEBUG_VALGRIND |
1571 | + /* Increase the timeouts if running under valgrind because it executes |
1572 | + extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that |
1573 | +--- a/storage/innobase/include/buf0buf.h |
1574 | ++++ b/storage/innobase/include/buf0buf.h |
1575 | +@@ -1509,6 +1509,8 @@ |
1576 | + frees a page in buffer pool */ |
1577 | + # endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
1578 | + #endif /* !UNIV_HOTBACKUP */ |
1579 | ++ ibool is_compacted; /*!< TRUE if the page was skipped in |
1580 | ++ compact backups */ |
1581 | + }; |
1582 | + |
1583 | + /** The buffer control block structure */ |
1584 | |
1585 | === modified file 'src/Makefile' |
1586 | --- src/Makefile 2013-01-07 06:19:24 +0000 |
1587 | +++ src/Makefile 2013-01-14 11:06:22 +0000 |
1588 | @@ -31,6 +31,7 @@ |
1589 | ds_buffer.o \ |
1590 | datasink.o \ |
1591 | write_filt.o \ |
1592 | + compact.o \ |
1593 | fil_cur.o \ |
1594 | innodb_int.o \ |
1595 | xbstream_write.o \ |
1596 | @@ -92,7 +93,7 @@ |
1597 | |
1598 | # XtraBackup for MySQL 5.5 |
1599 | 5.5: INC = $(COMMON_INC) $(addprefix -isystem$(MYSQL_ROOT_DIR)/, \ |
1600 | - include storage/innobase/include) |
1601 | + include storage/innobase/include sql) |
1602 | 5.5: INNODBOBJS = $(MYSQL_ROOT_DIR)/storage/innobase/libinnobase.a |
1603 | |
1604 | ifeq "$(wildcard $(MYSQL_ROOT_DIR)/zlib/.libs/libzlt.a)" "" |
1605 | @@ -157,7 +158,7 @@ |
1606 | |
1607 | # XtraBackup for XtraDB 5.5 |
1608 | xtradb55: INC = $(COMMON_INC) $(addprefix -isystem$(MYSQL_ROOT_DIR)/, \ |
1609 | - include storage/innobase/include) |
1610 | + include storage/innobase/include sql) |
1611 | xtradb55: INNODBOBJS = $(MYSQL_ROOT_DIR)/storage/innobase/libinnobase.a |
1612 | ifeq ($(shell uname -s),Linux) |
1613 | xtradb55: LIBS += -laio |
1614 | @@ -189,7 +190,7 @@ |
1615 | xbstream: $(XBSTREAMOBJS) $(MYSQLOBJS) ds_local.o ds_buffer.o datasink.o |
1616 | $(CC) $(CFLAGS) $^ $(INC) $(MYSQLOBJS) $(LIBS) -o $@ |
1617 | |
1618 | -xtrabackup.o: xtrabackup.c xb_regex.h write_filt.h fil_cur.h xtrabackup.h |
1619 | +xtrabackup.o: xtrabackup.c xb_regex.h write_filt.h fil_cur.h xtrabackup.h compact.h |
1620 | |
1621 | $(TARGET): $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBARCHIVE_A) |
1622 | $(CC) $(CFLAGS) $(XTRABACKUPOBJS) $(INNODBOBJS) $(MYSQLOBJS) $(LIBS) \ |
1623 | |
1624 | === added file 'src/compact.c' |
1625 | --- src/compact.c 1970-01-01 00:00:00 +0000 |
1626 | +++ src/compact.c 2013-01-14 11:06:22 +0000 |
1627 | @@ -0,0 +1,960 @@ |
1628 | +/****************************************************** |
1629 | +XtraBackup: hot backup tool for InnoDB |
1630 | +(c) 2009-2013 Percona Ireland Ltd. |
1631 | +Originally Created 3/3/2009 Yasufumi Kinoshita |
1632 | +Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, |
1633 | +Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. |
1634 | + |
1635 | +This program is free software; you can redistribute it and/or modify |
1636 | +it under the terms of the GNU General Public License as published by |
1637 | +the Free Software Foundation; version 2 of the License. |
1638 | + |
1639 | +This program is distributed in the hope that it will be useful, |
1640 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
1641 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1642 | +GNU General Public License for more details. |
1643 | + |
1644 | +You should have received a copy of the GNU General Public License |
1645 | +along with this program; if not, write to the Free Software |
1646 | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1647 | + |
1648 | +*******************************************************/ |
1649 | + |
1650 | +/* Compact backups implementation */ |
1651 | + |
1652 | +#include <my_base.h> |
1653 | +#include <page0page.h> |
1654 | +#include <dict0dict.h> |
1655 | +#include <dict0load.h> |
1656 | +#include <btr0pcur.h> |
1657 | +#include <ibuf0ibuf.h> |
1658 | +#include <row0merge.h> |
1659 | +#include <trx0trx.h> |
1660 | +#include <srv0srv.h> |
1661 | +#include "common.h" |
1662 | +#include "write_filt.h" |
1663 | +#include "fil_cur.h" |
1664 | +#include "xtrabackup.h" |
1665 | +#include "ds_buffer.h" |
1666 | +#include "xb0xb.h" |
1667 | + |
1668 | +/* Number of the first primary key page in an .ibd file */ |
1669 | +#define XB_FIRST_CLUSTERED_INDEX_PAGE_NO 3 |
1670 | + |
1671 | +/* Suffix for page map files */ |
1672 | +#define XB_PAGE_MAP_SUFFIX ".pmap" |
1673 | +#define XB_TMPFILE_SUFFIX ".tmp" |
1674 | + |
1675 | +/* Page range */ |
1676 | +typedef struct { |
1677 | + ulint from; /*!< range start */ |
1678 | + ulint to; /*!< range end */ |
1679 | +} page_range_t; |
1680 | + |
1681 | +/* Cursor in a page map file */ |
1682 | +typedef struct { |
1683 | + File fd; /*!< file descriptor */ |
1684 | + IO_CACHE cache; /*!< IO_CACHE associated with fd */ |
1685 | +} page_map_cursor_t; |
1686 | + |
1687 | +/* Empty page use to replace skipped pages in the data files */ |
1688 | +static byte empty_page[UNIV_PAGE_SIZE_MAX]; |
1689 | +static const char compacted_page_magic[] = "COMPACTP"; |
1690 | +static const size_t compacted_page_magic_size = |
1691 | + sizeof(compacted_page_magic) - 1; |
1692 | +static const ulint compacted_page_magic_offset = FIL_PAGE_DATA; |
1693 | + |
1694 | +/************************************************************************ |
1695 | +Compact page filter. */ |
1696 | +static my_bool wf_compact_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, |
1697 | + xb_fil_cur_t *cursor); |
1698 | +static my_bool wf_compact_process(xb_write_filt_ctxt_t *ctxt, |
1699 | + ds_file_t *dstfile); |
1700 | +static my_bool wf_compact_finalize(xb_write_filt_ctxt_t *ctxt, |
1701 | + ds_file_t *dstfile); |
1702 | +xb_write_filt_t wf_compact = { |
1703 | + &wf_compact_init, |
1704 | + &wf_compact_process, |
1705 | + &wf_compact_finalize, |
1706 | + NULL |
1707 | +}; |
1708 | + |
1709 | +/************************************************************************ |
1710 | +Initialize the compact page filter. |
1711 | + |
1712 | +@return TRUE on success, FALSE on error. */ |
1713 | +static my_bool |
1714 | +wf_compact_init(xb_write_filt_ctxt_t *ctxt, |
1715 | + char *dst_name __attribute__((unused)), xb_fil_cur_t *cursor) |
1716 | +{ |
1717 | + xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt); |
1718 | + char page_map_name[FN_REFLEN]; |
1719 | + MY_STAT mystat; |
1720 | + |
1721 | + ctxt->cursor = cursor; |
1722 | + cp->clustered_index_found = FALSE; |
1723 | + cp->inside_skipped_range = FALSE; |
1724 | + cp->free_limit = 0; |
1725 | + |
1726 | + /* Don't compact the system table space */ |
1727 | + cp->skip = cursor->is_system; |
1728 | + if (cp->skip) { |
1729 | + return(TRUE); |
1730 | + } |
1731 | + |
1732 | + snprintf(page_map_name, sizeof(page_map_name), "%s%s", dst_name, |
1733 | + XB_PAGE_MAP_SUFFIX); |
1734 | + |
1735 | + cp->ds_buffer = ds_create(xtrabackup_target_dir, DS_TYPE_BUFFER); |
1736 | + if (cp->ds_buffer == NULL) { |
1737 | + return(FALSE); |
1738 | + } |
1739 | + |
1740 | + ds_set_pipe(cp->ds_buffer, ds_meta); |
1741 | + |
1742 | + memset(&mystat, 0, sizeof(mystat)); |
1743 | + mystat.st_mtime = my_time(0); |
1744 | + cp->buffer = ds_open(cp->ds_buffer, page_map_name, &mystat); |
1745 | + if (cp->buffer == NULL) { |
1746 | + msg("xtrabackup: Error: cannot open output stream for %s\n", |
1747 | + page_map_name); |
1748 | + return(FALSE); |
1749 | + } |
1750 | + |
1751 | + return(TRUE); |
1752 | +} |
1753 | + |
1754 | +/************************************************************************ |
1755 | +Check if the specified page should be skipped. We currently skip all |
1756 | +non-clustered index pages for compact backups. |
1757 | + |
1758 | +@return TRUE if the page should be skipped. */ |
1759 | +static my_bool |
1760 | +check_if_skip_page(xb_wf_compact_ctxt_t *cp, xb_fil_cur_t *cursor, ulint offset) |
1761 | +{ |
1762 | + byte *page; |
1763 | + ulint page_no; |
1764 | + ulint page_type; |
1765 | + INDEX_ID_T index_id; |
1766 | + |
1767 | + |
1768 | + xb_ad(cursor->is_system == FALSE); |
1769 | + |
1770 | + page = cursor->buf + cursor->page_size * offset; |
1771 | + page_no = cursor->buf_page_no + offset; |
1772 | + page_type = fil_page_get_type(page); |
1773 | + |
1774 | + if (UNIV_UNLIKELY(page_no == 0)) { |
1775 | + |
1776 | + cp->free_limit = mach_read_from_4(page + FSP_HEADER_OFFSET + |
1777 | + FSP_FREE_LIMIT); |
1778 | + } else if (UNIV_UNLIKELY(page_no == XB_FIRST_CLUSTERED_INDEX_PAGE_NO)) { |
1779 | + |
1780 | + xb_ad(cp->clustered_index_found == FALSE); |
1781 | + |
1782 | + if (page_type != FIL_PAGE_INDEX) { |
1783 | + |
1784 | + /* Uninitialized clustered index root page, there's |
1785 | + nothing we can do to compact the space.*/ |
1786 | + |
1787 | + msg("[%02u] Uninitialized page type value (%lu) in the " |
1788 | + "clustered index root page of tablespace %s. " |
1789 | + "Will not be compacted.\n", |
1790 | + cursor->thread_n, |
1791 | + page_type, cursor->path); |
1792 | + |
1793 | + cp->skip = TRUE; |
1794 | + |
1795 | + return(FALSE); |
1796 | + } |
1797 | + |
1798 | + cp->clustered_index = |
1799 | + mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID); |
1800 | + cp->clustered_index_found = TRUE; |
1801 | + } else if (UNIV_UNLIKELY(page_no >= cp->free_limit)) { |
1802 | + |
1803 | + /* Skip unused pages above free limit, if that value is set in |
1804 | + the FSP header.*/ |
1805 | + |
1806 | + return(cp->free_limit > 0); |
1807 | + } else if (cp->clustered_index_found && page_type == FIL_PAGE_INDEX) { |
1808 | + |
1809 | + index_id = mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID); |
1810 | + if (INDEX_ID_CMP(index_id, cp->clustered_index) != 0) { |
1811 | + ulint fseg_hdr_space = |
1812 | + mach_read_from_4(page + PAGE_HEADER + |
1813 | + PAGE_BTR_SEG_TOP); |
1814 | + ulint fseg_hdr_page_no = |
1815 | + mach_read_from_4(page + PAGE_HEADER + |
1816 | + PAGE_BTR_SEG_TOP + 4); |
1817 | + ulint fseg_hdr_offset = |
1818 | + mach_read_from_2(page + PAGE_HEADER + |
1819 | + PAGE_BTR_SEG_TOP + 8); |
1820 | + |
1821 | + /* Don't skip root index pages, i.e. the ones where the |
1822 | + above fields are defined. We need root index pages to be |
1823 | + able to correctly drop the indexes later, as they |
1824 | + contain fseg inode pointers. */ |
1825 | + |
1826 | + return(fseg_hdr_space == 0 && |
1827 | + fseg_hdr_page_no == 0 && |
1828 | + fseg_hdr_offset == 0); |
1829 | + } |
1830 | + } |
1831 | + |
1832 | + return(FALSE); |
1833 | +} |
1834 | + |
1835 | +/************************************************************************ |
1836 | +Run the next batch of pages through the compact page filter. |
1837 | + |
1838 | +@return TRUE on success, FALSE on error. */ |
1839 | +static my_bool |
1840 | +wf_compact_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) |
1841 | +{ |
1842 | + xb_fil_cur_t *cursor = ctxt->cursor; |
1843 | + ulint page_size = cursor->page_size; |
1844 | + byte *page; |
1845 | + byte *buf_end; |
1846 | + byte *write_from; |
1847 | + xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt); |
1848 | + ulint i; |
1849 | + ulint page_no; |
1850 | + byte tmp[4]; |
1851 | + |
1852 | + if (cp->skip) { |
1853 | + return(!ds_write(dstfile, cursor->buf, cursor->buf_read)); |
1854 | + } |
1855 | + |
1856 | + write_from = NULL; |
1857 | + buf_end = cursor->buf + cursor->buf_read; |
1858 | + for (i = 0, page = cursor->buf; page < buf_end; |
1859 | + i++, page += page_size) { |
1860 | + |
1861 | + page_no = cursor->buf_page_no + i; |
1862 | + |
1863 | + if (!check_if_skip_page(cp, cursor, i)) { |
1864 | + |
1865 | + if (write_from == NULL) { |
1866 | + write_from = page; |
1867 | + } |
1868 | + |
1869 | + if (cp->inside_skipped_range) { |
1870 | + cp->inside_skipped_range = FALSE; |
1871 | + |
1872 | + /* Write the last range endpoint to the |
1873 | + skipped pages map */ |
1874 | + |
1875 | + xb_ad(page_no > 0); |
1876 | + mach_write_to_4(tmp, page_no - 1); |
1877 | + if (ds_write(cp->buffer, tmp, sizeof(tmp))) { |
1878 | + return(FALSE); |
1879 | + } |
1880 | + } |
1881 | + continue; |
1882 | + } |
1883 | + |
1884 | + if (write_from != NULL) { |
1885 | + |
1886 | + /* The first skipped page in this block, write the |
1887 | + non-skipped ones to the data file */ |
1888 | + |
1889 | + if (ds_write(dstfile, write_from, page - write_from)) { |
1890 | + return(FALSE); |
1891 | + } |
1892 | + |
1893 | + write_from = NULL; |
1894 | + } |
1895 | + |
1896 | + if (!cp->inside_skipped_range) { |
1897 | + |
1898 | + /* The first skipped page in range, write the first |
1899 | + range endpoint to the skipped pages map */ |
1900 | + |
1901 | + cp->inside_skipped_range = TRUE; |
1902 | + |
1903 | + mach_write_to_4(tmp, page_no); |
1904 | + if (ds_write(cp->buffer, tmp, sizeof(tmp))) { |
1905 | + return(FALSE); |
1906 | + } |
1907 | + } |
1908 | + } |
1909 | + |
1910 | + /* Write the remaining pages in the buffer, if any */ |
1911 | + if (write_from != NULL && |
1912 | + ds_write(dstfile, write_from, buf_end - write_from)) { |
1913 | + return(FALSE); |
1914 | + } |
1915 | + |
1916 | + return(TRUE); |
1917 | +} |
1918 | + |
1919 | +/************************************************************************ |
1920 | +Close the compact filter's page map stream. |
1921 | + |
1922 | +@return TRUE on success, FALSE on error. */ |
1923 | +static my_bool |
1924 | +wf_compact_finalize(xb_write_filt_ctxt_t *ctxt, |
1925 | + ds_file_t *dstfile __attribute__((unused))) |
1926 | +{ |
1927 | + xb_fil_cur_t *cursor = ctxt->cursor; |
1928 | + xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt); |
1929 | + |
1930 | + /* Write the last endpoint of the current range, if the last pages of |
1931 | + the space have been skipped. */ |
1932 | + if (cp->inside_skipped_range) { |
1933 | + byte tmp[4]; |
1934 | + |
1935 | + mach_write_to_4(tmp, cursor->space_size - 1); |
1936 | + if (ds_write(cp->buffer, tmp, sizeof(tmp))) { |
1937 | + return(FALSE); |
1938 | + } |
1939 | + |
1940 | + cp->inside_skipped_range = FALSE; |
1941 | + } |
1942 | + |
1943 | + if (cp->buffer) { |
1944 | + ds_close(cp->buffer); |
1945 | + } |
1946 | + if (cp->ds_buffer) { |
1947 | + ds_destroy(cp->ds_buffer); |
1948 | + } |
1949 | + |
1950 | + return(TRUE); |
1951 | +} |
1952 | + |
1953 | +/************************************************************************ |
1954 | +Open a page map file and return a cursor. |
1955 | + |
1956 | +@return page map cursor, or NULL if the file doesn't exist. */ |
1957 | +static page_map_cursor_t * |
1958 | +page_map_file_open(const char *path) |
1959 | +{ |
1960 | + MY_STAT statinfo; |
1961 | + page_map_cursor_t *pmap_cur; |
1962 | + int rc; |
1963 | + |
1964 | + if (my_stat(path, &statinfo, MYF(0)) == NULL) { |
1965 | + |
1966 | + return(NULL); |
1967 | + } |
1968 | + |
1969 | + /* The maximum possible page map file corresponds to a 64 TB tablespace |
1970 | + and the worst case when every other page was skipped. That is, 2^32/2 |
1971 | + page ranges = 16 GB. */ |
1972 | + xb_a(statinfo.st_size < (off_t) 16 * 1024 * 1024 * 1024); |
1973 | + |
1974 | + /* Must be a series of 8-byte tuples */ |
1975 | + xb_a(statinfo.st_size % 8 == 0); |
1976 | + |
1977 | + pmap_cur = (page_map_cursor_t *) my_malloc(sizeof(page_map_cursor_t), |
1978 | + MYF(MY_FAE)); |
1979 | + |
1980 | + pmap_cur->fd = my_open(path, O_RDONLY, MYF(MY_WME)); |
1981 | + xb_a(pmap_cur->fd != 0); |
1982 | + |
1983 | + rc = init_io_cache(&pmap_cur->cache, pmap_cur->fd, 0, READ_CACHE, |
1984 | + 0, 0, MYF(MY_WME)); |
1985 | + xb_a(rc == 0); |
1986 | + |
1987 | + return(pmap_cur); |
1988 | +} |
1989 | + |
1990 | +/************************************************************************ |
1991 | +Read the next range from a page map file and update the cursor. |
1992 | + |
1993 | +@return TRUE on success, FALSE on end-of-file. */ |
1994 | +static ibool |
1995 | +page_map_file_next(page_map_cursor_t *pmap_cur, page_range_t *range) |
1996 | +{ |
1997 | + byte buf[8]; |
1998 | + |
1999 | + xb_ad(pmap_cur != NULL); |
2000 | + |
2001 | + if (my_b_read(&pmap_cur->cache, buf, sizeof(buf))) { |
2002 | + return(FALSE); |
2003 | + } |
2004 | + |
2005 | + range->from = mach_read_from_4(buf); |
2006 | + range->to = mach_read_from_4(buf + 4); |
2007 | + |
2008 | + return(TRUE); |
2009 | +} |
2010 | + |
2011 | +/************************************************************************ |
2012 | +Close the page map cursor.*/ |
2013 | +static void |
2014 | +page_map_file_close(page_map_cursor_t *pmap_cur) |
2015 | +{ |
2016 | + int rc; |
2017 | + |
2018 | + xb_ad(pmap_cur != NULL); |
2019 | + |
2020 | + rc = end_io_cache(&pmap_cur->cache); |
2021 | + xb_a(rc == 0); |
2022 | + |
2023 | + posix_fadvise(pmap_cur->fd, 0, 0, POSIX_FADV_DONTNEED); |
2024 | + |
2025 | + rc = my_close(pmap_cur->fd, MY_WME); |
2026 | + xb_a(rc == 0); |
2027 | +} |
2028 | + |
2029 | +/**************************************************************************** |
2030 | +Expand a single data file according to the skipped pages maps created by |
2031 | +--compact. |
2032 | + |
2033 | +@return TRUE on success, FALSE on failure. */ |
2034 | +static my_bool |
2035 | +xb_expand_file(fil_node_t *node) |
2036 | +{ |
2037 | + char pmapfile_path[FN_REFLEN]; |
2038 | + char tmpfile_path[FN_REFLEN]; |
2039 | + xb_fil_cur_t cursor; |
2040 | + xb_fil_cur_result_t res; |
2041 | + ds_ctxt_t *ds_local; |
2042 | + ds_ctxt_t *ds_buffer; |
2043 | + ds_file_t *tmpfile; |
2044 | + my_bool success = FALSE; |
2045 | + ulint i; |
2046 | + byte *page; |
2047 | + ulint page_expected_no; |
2048 | + page_map_cursor_t *pmap_cur; |
2049 | + ibool have_next_range; |
2050 | + page_range_t pmap_range; |
2051 | + |
2052 | + xb_ad(trx_sys_sys_space(node->space->id) == FALSE); |
2053 | + |
2054 | + snprintf(pmapfile_path, sizeof(pmapfile_path), "%s%s", |
2055 | + node->name, XB_PAGE_MAP_SUFFIX); |
2056 | + |
2057 | + /* Skip files that don't have a corresponding page map file */ |
2058 | + |
2059 | + if (!(pmap_cur = page_map_file_open(pmapfile_path))) { |
2060 | + |
2061 | + msg("Not expanding %s\n", node->name); |
2062 | + |
2063 | + return(FALSE); |
2064 | + } |
2065 | + |
2066 | + msg("Expanding %s\n", node->name); |
2067 | + |
2068 | + ds_local = ds_create(".", DS_TYPE_LOCAL); |
2069 | + ds_buffer = ds_create(".", DS_TYPE_BUFFER); |
2070 | + |
2071 | + xb_a(ds_local != NULL && ds_buffer != NULL); |
2072 | + |
2073 | + ds_buffer_set_size(ds_buffer, FSP_EXTENT_SIZE * UNIV_PAGE_SIZE_MAX); |
2074 | + |
2075 | + ds_set_pipe(ds_buffer, ds_local); |
2076 | + |
2077 | + res = xb_fil_cur_open(&cursor, node, 1); |
2078 | + xb_a(res == XB_FIL_CUR_SUCCESS); |
2079 | + |
2080 | + snprintf(tmpfile_path, sizeof(tmpfile_path), "%s%s", |
2081 | + node->name, XB_TMPFILE_SUFFIX); |
2082 | + |
2083 | + tmpfile = ds_open(ds_buffer, tmpfile_path, &cursor.statinfo); |
2084 | + if (tmpfile == NULL) { |
2085 | + |
2086 | + msg("Could not open temporary file '%s'\n", tmpfile_path); |
2087 | + goto error; |
2088 | + } |
2089 | + |
2090 | + have_next_range = page_map_file_next(pmap_cur, &pmap_range); |
2091 | + |
2092 | + page_expected_no = 0; |
2093 | + |
2094 | + /* Initialize and mark the empty page which is used to replace |
2095 | + skipped pages. */ |
2096 | + memset(empty_page, 0, cursor.page_size); |
2097 | + memcpy(empty_page + compacted_page_magic_offset, |
2098 | + compacted_page_magic, compacted_page_magic_size); |
2099 | + mach_write_to_4(empty_page + FIL_PAGE_SPACE_OR_CHKSUM, |
2100 | + BUF_NO_CHECKSUM_MAGIC); |
2101 | + mach_write_to_4(empty_page + cursor.page_size - |
2102 | + FIL_PAGE_END_LSN_OLD_CHKSUM, |
2103 | + BUF_NO_CHECKSUM_MAGIC); |
2104 | + |
2105 | + |
2106 | + /* Main copy loop */ |
2107 | + |
2108 | + while ((res = xb_fil_cur_read(&cursor)) == XB_FIL_CUR_SUCCESS) { |
2109 | + |
2110 | + for (i = 0, page = cursor.buf; i < cursor.buf_npages; |
2111 | + i++, page += cursor.page_size) { |
2112 | + |
2113 | + ulint page_read_no; |
2114 | + |
2115 | + page_read_no = mach_read_from_4(page + FIL_PAGE_OFFSET); |
2116 | + xb_a(!page_read_no || page_expected_no <= page_read_no); |
2117 | + |
2118 | + if (have_next_range && |
2119 | + page_expected_no == pmap_range.from) { |
2120 | + |
2121 | + xb_a(pmap_range.from <= pmap_range.to); |
2122 | + |
2123 | + /* Write empty pages instead of skipped ones, if |
2124 | + necessary. */ |
2125 | + |
2126 | + while (page_expected_no <= pmap_range.to) { |
2127 | + |
2128 | + if (ds_write(tmpfile, empty_page, |
2129 | + cursor.page_size)) { |
2130 | + |
2131 | + goto write_error; |
2132 | + } |
2133 | + |
2134 | + page_expected_no++; |
2135 | + } |
2136 | + |
2137 | + have_next_range = |
2138 | + page_map_file_next(pmap_cur, |
2139 | + &pmap_range); |
2140 | + } |
2141 | + |
2142 | + /* Write the current page */ |
2143 | + |
2144 | + if (ds_write(tmpfile, page, cursor.page_size)) { |
2145 | + |
2146 | + goto write_error; |
2147 | + } |
2148 | + |
2149 | + page_expected_no++; |
2150 | + } |
2151 | + } |
2152 | + |
2153 | + if (res != XB_FIL_CUR_EOF) { |
2154 | + |
2155 | + goto error; |
2156 | + } |
2157 | + |
2158 | + /* Write empty pages instead of trailing skipped ones, if any */ |
2159 | + |
2160 | + if (have_next_range) { |
2161 | + |
2162 | + xb_a(page_expected_no == pmap_range.from); |
2163 | + xb_a(pmap_range.from <= pmap_range.to); |
2164 | + |
2165 | + while (page_expected_no <= pmap_range.to) { |
2166 | + |
2167 | + if (ds_write(tmpfile, empty_page, |
2168 | + cursor.page_size)) { |
2169 | + |
2170 | + goto write_error; |
2171 | + } |
2172 | + |
2173 | + page_expected_no++; |
2174 | + } |
2175 | + |
2176 | + xb_a(!page_map_file_next(pmap_cur, &pmap_range)); |
2177 | + } |
2178 | + |
2179 | + /* Replace the original .ibd file with the expanded file */ |
2180 | + if (my_rename(tmpfile_path, node->name, MYF(MY_WME))) { |
2181 | + |
2182 | + msg("Failed to rename '%s' to '%s'\n", |
2183 | + tmpfile_path, node->name); |
2184 | + goto error; |
2185 | + } |
2186 | + |
2187 | + my_delete(pmapfile_path, MYF(MY_WME)); |
2188 | + |
2189 | + ds_close(tmpfile); |
2190 | + tmpfile = NULL; |
2191 | + |
2192 | + success = TRUE; |
2193 | + |
2194 | + goto end; |
2195 | + |
2196 | +write_error: |
2197 | + msg("Write to '%s' failed\n", tmpfile_path); |
2198 | + |
2199 | +error: |
2200 | + if (tmpfile != NULL) { |
2201 | + |
2202 | + ds_close(tmpfile); |
2203 | + my_delete(tmpfile_path, MYF(MY_WME)); |
2204 | + } |
2205 | + |
2206 | +end: |
2207 | + ds_destroy(ds_buffer); |
2208 | + ds_destroy(ds_local); |
2209 | + |
2210 | + page_map_file_close(pmap_cur); |
2211 | + |
2212 | + return(success); |
2213 | +} |
2214 | + |
2215 | +/****************************************************************************** |
2216 | +Expand the data files according to the skipped pages maps created by --compact. |
2217 | +@return TRUE on success, FALSE on failure. */ |
2218 | +my_bool |
2219 | +xb_expand_datafiles(void) |
2220 | +/*=====================*/ |
2221 | +{ |
2222 | + ulint nfiles; |
2223 | + datafiles_iter_t *it = NULL; |
2224 | + fil_node_t *node; |
2225 | + fil_space_t *space; |
2226 | + |
2227 | + msg("Starting to expand compacted .ibd files.\n"); |
2228 | + |
2229 | + /* Initialize the tablespace cache */ |
2230 | + if (xb_data_files_init() != DB_SUCCESS) { |
2231 | + return(FALSE); |
2232 | + } |
2233 | + |
2234 | + nfiles = UT_LIST_GET_LEN(fil_system->space_list); |
2235 | + xb_a(nfiles > 0); |
2236 | + |
2237 | + it = datafiles_iter_new(fil_system); |
2238 | + if (it == NULL) { |
2239 | + msg("xtrabackup: error: datafiles_iter_new() failed.\n"); |
2240 | + goto error; |
2241 | + } |
2242 | + |
2243 | + while ((node = datafiles_iter_next(it)) != NULL) { |
2244 | + |
2245 | + space = node->space; |
2246 | + |
2247 | + /* System tablespace cannot be compacted */ |
2248 | + if (trx_sys_sys_space(space->id)) { |
2249 | + |
2250 | + continue; |
2251 | + } |
2252 | + |
2253 | + if (!xb_expand_file(node)) { |
2254 | + |
2255 | + goto error; |
2256 | + } |
2257 | + } |
2258 | + |
2259 | + datafiles_iter_free(it); |
2260 | + xb_data_files_close(); |
2261 | + |
2262 | + return(TRUE); |
2263 | + |
2264 | +error: |
2265 | + if (it != NULL) { |
2266 | + datafiles_iter_free(it); |
2267 | + } |
2268 | + |
2269 | + xb_data_files_close(); |
2270 | + |
2271 | + return(FALSE); |
2272 | +} |
2273 | + |
2274 | +/****************************************************************************** |
2275 | +Callback used in buf_page_io_complete() to detect compacted pages. |
2276 | +@return TRUE if the page is marked as compacted, FALSE otherwise. */ |
2277 | +ibool |
2278 | +buf_page_is_compacted( |
2279 | +/*==================*/ |
2280 | + const byte* page) /*!< in: a database page */ |
2281 | +{ |
2282 | + return !memcmp(page + compacted_page_magic_offset, |
2283 | + compacted_page_magic, compacted_page_magic_size); |
2284 | +} |
2285 | + |
2286 | +/********************************************************************//** |
2287 | +Determine the flags of a table described in SYS_TABLES. |
2288 | +@return compressed page size in kilobytes; or 0 if the tablespace is |
2289 | +uncompressed, ULINT_UNDEFINED on error */ |
2290 | +static |
2291 | +ulint |
2292 | +dict_sys_tables_get_flags( |
2293 | +/*======================*/ |
2294 | + const rec_t* rec) /*!< in: a record of SYS_TABLES */ |
2295 | +{ |
2296 | + const byte* field; |
2297 | + ulint len; |
2298 | + ulint n_cols; |
2299 | + ulint flags; |
2300 | + |
2301 | + field = rec_get_nth_field_old(rec, 5, &len); |
2302 | + ut_a(len == 4); |
2303 | + |
2304 | + flags = mach_read_from_4(field); |
2305 | + |
2306 | + if (UNIV_LIKELY(flags == DICT_TABLE_ORDINARY)) { |
2307 | + return(0); |
2308 | + } |
2309 | + |
2310 | + field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len); |
2311 | + n_cols = mach_read_from_4(field); |
2312 | + |
2313 | + if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) { |
2314 | + /* New file formats require ROW_FORMAT=COMPACT. */ |
2315 | + return(ULINT_UNDEFINED); |
2316 | + } |
2317 | + |
2318 | + switch (flags & (DICT_TF_FORMAT_MASK | DICT_TF_COMPACT)) { |
2319 | + default: |
2320 | + case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT: |
2321 | + case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT: |
2322 | + /* flags should be DICT_TABLE_ORDINARY, |
2323 | + or DICT_TF_FORMAT_MASK should be nonzero. */ |
2324 | + return(ULINT_UNDEFINED); |
2325 | + |
2326 | + case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT: |
2327 | + /* We support this format. */ |
2328 | + break; |
2329 | + } |
2330 | + |
2331 | + if (UNIV_UNLIKELY((flags & DICT_TF_ZSSIZE_MASK) |
2332 | + > (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT))) { |
2333 | + /* Unsupported compressed page size. */ |
2334 | + return(ULINT_UNDEFINED); |
2335 | + } |
2336 | + |
2337 | + if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) { |
2338 | + /* Some unused bits are set. */ |
2339 | + return(ULINT_UNDEFINED); |
2340 | + } |
2341 | + |
2342 | + return(flags); |
2343 | +} |
2344 | + |
2345 | +/***************************************************************************** |
2346 | +Builds an index definition corresponding to an index object. It is roughly |
2347 | +similar to innobase_create_index_def() / innobase_create_index_field_def() and |
2348 | +the opposite to dict_mem_index_create() / dict_mem_index_add_field(). */ |
2349 | +static |
2350 | +void |
2351 | +xb_build_index_def( |
2352 | +/*=======================*/ |
2353 | + mem_heap_t* heap, /*!< in: heap */ |
2354 | + const dict_index_t* index, /*!< in: index */ |
2355 | + merge_index_def_t* index_def) /*!< out: index definition */ |
2356 | +{ |
2357 | + merge_index_field_t* fields; |
2358 | + ulint n_fields; |
2359 | + ulint i; |
2360 | + |
2361 | + ut_a(index->n_fields); |
2362 | + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); |
2363 | + |
2364 | + /* Use n_user_defined_cols instead of n_fields, as the index will |
2365 | + contain a part of the primary key after n_user_defined_cols, and those |
2366 | + columns will be created automatically in |
2367 | + dict_index_build_internal_clust(). */ |
2368 | + n_fields = index->n_user_defined_cols; |
2369 | + |
2370 | + memset(index_def, 0, sizeof(*index_def)); |
2371 | + |
2372 | + index_def->name = mem_heap_strdup(heap, index->name); |
2373 | + index_def->ind_type = index->type; |
2374 | + |
2375 | + fields = mem_heap_alloc(heap, n_fields * sizeof(*fields)); |
2376 | + |
2377 | + for (i = 0; i < n_fields; i++) { |
2378 | + dict_field_t* field; |
2379 | + |
2380 | + field = dict_index_get_nth_field(index, i); |
2381 | + |
2382 | + fields[i].field_name = mem_heap_strdup(heap, field->name); |
2383 | + fields[i].prefix_len = field->prefix_len; |
2384 | + } |
2385 | + |
2386 | + index_def->fields = fields; |
2387 | + index_def->n_fields = n_fields; |
2388 | +} |
2389 | + |
2390 | +/********************************************************************//** |
2391 | +Rebuild secondary indexes for a given table. */ |
2392 | +static |
2393 | +void |
2394 | +xb_rebuild_indexes_for_table( |
2395 | +/*=======================*/ |
2396 | + dict_table_t* table, /*!< in: table */ |
2397 | + trx_t* trx) /*!< in: transaction handle */ |
2398 | +{ |
2399 | + dict_index_t* index; |
2400 | + dict_index_t** indexes; |
2401 | + ulint n_indexes; |
2402 | + merge_index_def_t* index_defs; |
2403 | + ulint i; |
2404 | + mem_heap_t* heap; |
2405 | + ulint error; |
2406 | + |
2407 | + ut_ad(mutex_own(&(dict_sys->mutex))); |
2408 | + ut_ad(table); |
2409 | + |
2410 | + ut_a(UT_LIST_GET_LEN(table->indexes) > 0); |
2411 | + |
2412 | + n_indexes = UT_LIST_GET_LEN(table->indexes) - 1; |
2413 | + if (!n_indexes) { |
2414 | + /* Only the primary key, nothing to do. */ |
2415 | + return; |
2416 | + } |
2417 | + |
2418 | + heap = mem_heap_create(1024); |
2419 | + |
2420 | + indexes = (dict_index_t**) mem_heap_alloc(heap, |
2421 | + n_indexes * sizeof(*indexes)); |
2422 | + index_defs = (merge_index_def_t*) mem_heap_alloc(heap, |
2423 | + n_indexes * |
2424 | + sizeof(*index_defs)); |
2425 | + |
2426 | + /* Skip the primary key. */ |
2427 | + index = dict_table_get_first_index(table); |
2428 | + ut_a(dict_index_is_clust(index)); |
2429 | + |
2430 | + for (i = 0; (index = dict_table_get_next_index(index)); i++) { |
2431 | + |
2432 | + msg(" Found index %s\n", index->name); |
2433 | + |
2434 | + indexes[i] = index; |
2435 | + |
2436 | + xb_build_index_def(heap, index, &index_defs[i]); |
2437 | + } |
2438 | + |
2439 | + ut_ad(i == n_indexes); |
2440 | + |
2441 | + msg(" Dropping %lu index(es).\n", n_indexes); |
2442 | + |
2443 | + row_merge_drop_indexes(trx, table, indexes, n_indexes); |
2444 | + |
2445 | + msg(" Rebuilding %lu index(es).\n", n_indexes); |
2446 | + |
2447 | + row_merge_lock_table(trx, table, LOCK_X); |
2448 | + |
2449 | + for (i = 0; i < n_indexes; i++) { |
2450 | + indexes[i] = row_merge_create_index(trx, table, &index_defs[i]); |
2451 | + } |
2452 | + |
2453 | + error = row_merge_build_indexes(trx, table, table, indexes, n_indexes, |
2454 | + NULL); |
2455 | + ut_a(error == DB_SUCCESS); |
2456 | + |
2457 | + mem_heap_free(heap); |
2458 | +} |
2459 | + |
2460 | +/****************************************************************************** |
2461 | +Rebuild all secondary indexes in all tables in separate spaces. Called from |
2462 | +innobase_start_or_create_for_mysql(). */ |
2463 | +void |
2464 | +xb_compact_rebuild_indexes(void) |
2465 | +/*=============================*/ |
2466 | +{ |
2467 | + dict_table_t* sys_tables; |
2468 | + dict_index_t* sys_index; |
2469 | + btr_pcur_t pcur; |
2470 | + const rec_t* rec; |
2471 | + mtr_t mtr; |
2472 | + const byte* field; |
2473 | + ulint len; |
2474 | + ulint space_id; |
2475 | + ulint flags; |
2476 | + char* name; |
2477 | + dict_table_t* table; |
2478 | + trx_t* trx; |
2479 | + |
2480 | + /* Iterate all tables that are not in the system tablespace. */ |
2481 | + |
2482 | + trx = trx_allocate_for_mysql(); |
2483 | + |
2484 | + /* Suppress foreign key checks, as we are going to drop and recreate all |
2485 | + secondary keys. */ |
2486 | + trx->check_foreigns = FALSE; |
2487 | + |
2488 | + row_mysql_lock_data_dictionary(trx); |
2489 | + |
2490 | + /* Enlarge the fatal lock wait timeout during index rebuild |
2491 | + operation. */ |
2492 | + mutex_enter(&kernel_mutex); |
2493 | + srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ |
2494 | + mutex_exit(&kernel_mutex); |
2495 | + |
2496 | + mtr_start(&mtr); |
2497 | + |
2498 | + sys_tables = dict_table_get_low("SYS_TABLES"); |
2499 | + sys_index = UT_LIST_GET_FIRST(sys_tables->indexes); |
2500 | + ut_a(!dict_table_is_comp(sys_tables)); |
2501 | + |
2502 | + btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur, |
2503 | + TRUE, &mtr); |
2504 | + for (;;) { |
2505 | + btr_pcur_move_to_next_user_rec(&pcur, &mtr); |
2506 | + |
2507 | + rec = btr_pcur_get_rec(&pcur); |
2508 | + |
2509 | + if (!btr_pcur_is_on_user_rec(&pcur)) { |
2510 | + /* end of index */ |
2511 | + |
2512 | + break; |
2513 | + } |
2514 | + |
2515 | + if (rec_get_deleted_flag(rec, 0)) { |
2516 | + continue; |
2517 | + } |
2518 | + |
2519 | + field = rec_get_nth_field_old(rec, 9, &len); |
2520 | + ut_a(len == 4); |
2521 | + |
2522 | + space_id = mach_read_from_4(field); |
2523 | + |
2524 | + /* Don't touch tables in the system tablespace */ |
2525 | + if (trx_sys_sys_space(space_id)) { |
2526 | + |
2527 | + continue; |
2528 | + } |
2529 | + |
2530 | + field = rec_get_nth_field_old(rec, 0, &len); |
2531 | + name = mem_strdupl((char*) field, len); |
2532 | + |
2533 | + flags = dict_sys_tables_get_flags(rec); |
2534 | + if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) { |
2535 | + |
2536 | + field = rec_get_nth_field_old(rec, 5, &len); |
2537 | + flags = mach_read_from_4(field); |
2538 | + |
2539 | + ut_print_timestamp(stderr); |
2540 | + fputs(" InnoDB: Error: table ", stderr); |
2541 | + ut_print_filename(stderr, name); |
2542 | + fprintf(stderr, "\n" |
2543 | + "InnoDB: in InnoDB data dictionary" |
2544 | + " has unknown type %lx.\n", |
2545 | + (ulong) flags); |
2546 | + |
2547 | + mem_free(name); |
2548 | + |
2549 | + continue; |
2550 | + } |
2551 | + |
2552 | + btr_pcur_store_position(&pcur, &mtr); |
2553 | + |
2554 | + mtr_commit(&mtr); |
2555 | + |
2556 | + table = dict_table_get_low(name); |
2557 | + ut_a(table != NULL); |
2558 | + |
2559 | + /* Discard change buffer entries for this space */ |
2560 | + ibuf_delete_for_discarded_space(space_id); |
2561 | + |
2562 | + msg("Rebuilding indexes for table %s (space id: %lu)\n", name, |
2563 | + space_id); |
2564 | + |
2565 | + xb_rebuild_indexes_for_table(table, trx); |
2566 | + |
2567 | + mem_free(name); |
2568 | + |
2569 | + /* Temporarily unlock the data dictionary to avoid long |
2570 | + semaphore waits. */ |
2571 | + row_mysql_unlock_data_dictionary(trx); |
2572 | + row_mysql_lock_data_dictionary(trx); |
2573 | + |
2574 | + mtr_start(&mtr); |
2575 | + |
2576 | + btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr); |
2577 | + } |
2578 | + |
2579 | + btr_pcur_close(&pcur); |
2580 | + mtr_commit(&mtr); |
2581 | + |
2582 | + row_mysql_unlock_data_dictionary(trx); |
2583 | + |
2584 | + trx_commit_for_mysql(trx); |
2585 | + |
2586 | + trx_free_for_mysql(trx); |
2587 | +} |
2588 | |
2589 | === added file 'src/compact.h' |
2590 | --- src/compact.h 1970-01-01 00:00:00 +0000 |
2591 | +++ src/compact.h 2013-01-14 11:06:22 +0000 |
2592 | @@ -0,0 +1,44 @@ |
2593 | +/****************************************************** |
2594 | +XtraBackup: hot backup tool for InnoDB |
2595 | +(c) 2009-2012 Percona Ireland Ltd. |
2596 | +Originally Created 3/3/2009 Yasufumi Kinoshita |
2597 | +Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, |
2598 | +Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. |
2599 | + |
2600 | +This program is free software; you can redistribute it and/or modify |
2601 | +it under the terms of the GNU General Public License as published by |
2602 | +the Free Software Foundation; version 2 of the License. |
2603 | + |
2604 | +This program is distributed in the hope that it will be useful, |
2605 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
2606 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2607 | +GNU General Public License for more details. |
2608 | + |
2609 | +You should have received a copy of the GNU General Public License |
2610 | +along with this program; if not, write to the Free Software |
2611 | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
2612 | + |
2613 | +*******************************************************/ |
2614 | + |
2615 | +#ifndef XB_COMPACT_H |
2616 | +#define XB_COMPACT_H |
2617 | + |
2618 | +#include "write_filt.h" |
2619 | + |
2620 | +/* Compact page filter context */ |
2621 | +typedef struct { |
2622 | + my_bool skip; |
2623 | + ds_ctxt_t *ds_buffer; |
2624 | + ds_file_t *buffer; |
2625 | + INDEX_ID_T clustered_index; |
2626 | + my_bool clustered_index_found; |
2627 | + my_bool inside_skipped_range; |
2628 | + ulint free_limit; |
2629 | +} xb_wf_compact_ctxt_t; |
2630 | + |
2631 | +/****************************************************************************** |
2632 | +Expand the data files according to the skipped pages maps created by --compact. |
2633 | +@return TRUE on success, FALSE on failure. */ |
2634 | +my_bool xb_expand_datafiles(void); |
2635 | + |
2636 | +#endif |
2637 | |
2638 | === modified file 'src/datasink.c' |
2639 | --- src/datasink.c 2013-01-13 12:29:50 +0000 |
2640 | +++ src/datasink.c 2013-01-14 11:06:22 +0000 |
2641 | @@ -53,6 +53,7 @@ |
2642 | break; |
2643 | default: |
2644 | msg("Unknown datasink type: %d\n", type); |
2645 | + xb_ad(0); |
2646 | return NULL; |
2647 | } |
2648 | |
2649 | |
2650 | === modified file 'src/ds_tmpfile.c' |
2651 | --- src/ds_tmpfile.c 2013-01-11 13:00:50 +0000 |
2652 | +++ src/ds_tmpfile.c 2013-01-14 11:06:22 +0000 |
2653 | @@ -182,7 +182,7 @@ |
2654 | xb_a(pipe_ctxt != NULL); |
2655 | |
2656 | buf = my_malloc(buf_size, MYF(MY_FAE)); |
2657 | - |
2658 | + |
2659 | tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr; |
2660 | list = tmpfile_ctxt->file_list; |
2661 | |
2662 | |
2663 | === modified file 'src/fil_cur.c' |
2664 | --- src/fil_cur.c 2013-01-11 13:00:50 +0000 |
2665 | +++ src/fil_cur.c 2013-01-14 11:06:22 +0000 |
2666 | @@ -142,6 +142,8 @@ |
2667 | cursor->buf_page_no = 0; |
2668 | cursor->thread_n = thread_n; |
2669 | |
2670 | + cursor->space_size = cursor->statinfo.st_size / page_size; |
2671 | + |
2672 | return(XB_FIL_CUR_SUCCESS); |
2673 | } |
2674 | |
2675 | @@ -216,13 +218,13 @@ |
2676 | page_no < FSP_EXTENT_SIZE * 3) { |
2677 | /* skip doublewrite buffer pages */ |
2678 | ut_a(page_size == UNIV_PAGE_SIZE); |
2679 | - msg("[%02lu] xtrabackup: " |
2680 | + msg("[%02u] xtrabackup: " |
2681 | "Page %lu is a doublewrite buffer page, " |
2682 | "skipping.\n", cursor->thread_n, page_no); |
2683 | } else { |
2684 | retry_count--; |
2685 | if (retry_count == 0) { |
2686 | - msg("[%02lu] xtrabackup: " |
2687 | + msg("[%02u] xtrabackup: " |
2688 | "Error: failed to read page after " |
2689 | "10 retries. File %s seems to be " |
2690 | "corrupted.\n", cursor->thread_n, |
2691 | @@ -230,7 +232,7 @@ |
2692 | ret = XB_FIL_CUR_ERROR; |
2693 | break; |
2694 | } |
2695 | - msg("[%02lu] xtrabackup: " |
2696 | + msg("[%02u] xtrabackup: " |
2697 | "Database page corruption detected at page " |
2698 | "%lu, retrying...\n", cursor->thread_n, |
2699 | page_no); |
2700 | |
2701 | === modified file 'src/fil_cur.h' |
2702 | --- src/fil_cur.h 2013-01-11 13:00:50 +0000 |
2703 | +++ src/fil_cur.h 2013-01-14 11:06:22 +0000 |
2704 | @@ -52,8 +52,9 @@ |
2705 | buffer */ |
2706 | ulint buf_page_no; /*!< number of the first page in |
2707 | buffer */ |
2708 | - ulint thread_n; /*!< thread number for diagnostics */ |
2709 | + uint thread_n; /*!< thread number for diagnostics */ |
2710 | ulint space_id; /*!< ID of tablespace */ |
2711 | + ulint space_size; /*!< space size in pages */ |
2712 | } xb_fil_cur_t; |
2713 | |
2714 | typedef enum { |
2715 | |
2716 | === modified file 'src/innodb_int.c' |
2717 | --- src/innodb_int.c 2013-01-11 13:00:50 +0000 |
2718 | +++ src/innodb_int.c 2013-01-14 11:06:22 +0000 |
2719 | @@ -28,8 +28,20 @@ |
2720 | #include <srv0srv.h> |
2721 | #include <ha_prototypes.h> |
2722 | #include <trx0trx.h> |
2723 | +#include <buf0flu.h> |
2724 | +#ifdef INNODB_VERSION_SHORT |
2725 | +# include <page0zip.h> |
2726 | +#endif |
2727 | +#if MYSQL_VERSION_ID < 50500 |
2728 | +# include <row0types.h> |
2729 | +#endif |
2730 | #include "common.h" |
2731 | |
2732 | +/* Required by innobase_rec*() stubs */ |
2733 | +#if MYSQL_VERSION_ID >= 50500 |
2734 | +typedef struct st_table TABLE; |
2735 | +#endif |
2736 | + |
2737 | extern long innobase_lock_wait_timeout; |
2738 | |
2739 | char *opt_mysql_tmpdir = NULL; |
2740 | @@ -901,6 +913,27 @@ |
2741 | return(fd2); |
2742 | } |
2743 | |
2744 | +/* The following is used by row0merge for error reporting. Define a stub so we |
2745 | +can use fast index creation from XtraBackup. */ |
2746 | +void |
2747 | +innobase_rec_reset( |
2748 | +/*===============*/ |
2749 | + TABLE* table __attribute__((unused))) |
2750 | +{ |
2751 | +} |
2752 | + |
2753 | +/* The following is used by row0merge for error reporting. Define a stub so we |
2754 | +can use fast index creation from XtraBackup. */ |
2755 | +void |
2756 | +innobase_rec_to_mysql( |
2757 | +/*==================*/ |
2758 | + TABLE* table __attribute__((unused)), |
2759 | + const rec_t* rec __attribute__((unused)), |
2760 | + const dict_index_t* index __attribute__((unused)), |
2761 | + const ulint* offsets __attribute__((unused))) |
2762 | +{ |
2763 | +} |
2764 | + |
2765 | #if MYSQL_VERSION_ID >= 50507 |
2766 | /* |
2767 | As of MySQL 5.5.7, InnoDB uses thd_wait plugin service. |
2768 | @@ -923,3 +956,15 @@ |
2769 | } |
2770 | |
2771 | #endif /* MYSQL_VERSION_ID >= 50507 */ |
2772 | + |
2773 | +#ifdef XTRADB_BASED |
2774 | +/******************************************************************//******* |
2775 | +Stub for an XtraDB-specific function called from row_merge_build_indexes().*/ |
2776 | +ibool |
2777 | +thd_expand_fast_index_creation( |
2778 | +/*================================*/ |
2779 | + void* thd __attribute__((unused))) |
2780 | +{ |
2781 | + return(FALSE); |
2782 | +} |
2783 | +#endif /* XTRADB_BASED */ |
2784 | |
2785 | === modified file 'src/innodb_int.h' |
2786 | --- src/innodb_int.h 2013-01-11 13:00:50 +0000 |
2787 | +++ src/innodb_int.h 2013-01-14 11:06:22 +0000 |
2788 | @@ -40,10 +40,16 @@ |
2789 | # if (MYSQL_VERSION_ID < 50500) |
2790 | # define MACH_READ_64 mach_read_ull |
2791 | # define MACH_WRITE_64 mach_write_ull |
2792 | +# define INDEX_ID_T dulint |
2793 | +# define INDEX_ID_CMP(a,b) ((a).high != (b).high ? \ |
2794 | + ((a).high - (b).high) : \ |
2795 | + ((a).low - (b).low)) |
2796 | # define OS_MUTEX_CREATE() os_mutex_create(NULL) |
2797 | # else |
2798 | # define MACH_READ_64 mach_read_from_8 |
2799 | # define MACH_WRITE_64 mach_write_to_8 |
2800 | +# define INDEX_ID_T index_id_t |
2801 | +# define INDEX_ID_CMP(a,b) ((a) - (b)) |
2802 | # define OS_MUTEX_CREATE() os_mutex_create() |
2803 | # endif |
2804 | # define xb_buf_page_is_corrupted(page, zip_size) \ |
2805 | @@ -86,6 +92,22 @@ |
2806 | HASH_SEARCH(NAME, TABLE, FOLD, xtrabackup_tables_t*, DATA, ASSERTION, \ |
2807 | TEST) |
2808 | |
2809 | +/* The following constants have been copied from fsp0fsp.c */ |
2810 | +#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header |
2811 | + within a file page */ |
2812 | +#define FSP_SIZE 8 /* Current size of the space in |
2813 | + pages */ |
2814 | +#define FSP_FREE_LIMIT 12 /* Minimum page number for which the |
2815 | + free list has not been initialized: |
2816 | + the pages >= this limit are, by |
2817 | + definition, free; note that in a |
2818 | + single-table tablespace where size |
2819 | + < 64 pages, this number is 64, i.e., |
2820 | + we have initialized the space |
2821 | + about the first extent, but have not |
2822 | + physically allocted those pages to the |
2823 | + file */ |
2824 | + |
2825 | /* ==start === definition at fil0fil.c === */ |
2826 | // ################################################################## |
2827 | // NOTE: We should check the following definitions fit to the source. |
2828 | |
2829 | === modified file 'src/write_filt.c' |
2830 | --- src/write_filt.c 2013-01-11 13:00:50 +0000 |
2831 | +++ src/write_filt.c 2013-01-14 11:06:22 +0000 |
2832 | @@ -62,22 +62,6 @@ |
2833 | }; |
2834 | |
2835 | /************************************************************************ |
2836 | -Compact page write filter. */ |
2837 | -static my_bool wf_compact_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, |
2838 | - xb_fil_cur_t *cursor); |
2839 | -static my_bool wf_compact_process(xb_write_filt_ctxt_t *ctxt, |
2840 | - ds_file_t *dstfile); |
2841 | -static my_bool wf_compact_finalize(xb_write_filt_ctxt_t *ctxt, |
2842 | - ds_file_t *dstfile); |
2843 | - |
2844 | -xb_write_filt_t wf_compact = { |
2845 | - &wf_compact_init, |
2846 | - &wf_compact_process, |
2847 | - &wf_compact_finalize, |
2848 | - NULL |
2849 | -}; |
2850 | - |
2851 | -/************************************************************************ |
2852 | Initialize incremental page write filter. |
2853 | |
2854 | @return TRUE on success, FALSE on error. */ |
2855 | @@ -106,7 +90,7 @@ |
2856 | info.zip_size = cursor->zip_size; |
2857 | info.space_id = cursor->space_id; |
2858 | if (!xb_write_delta_metadata(meta_name, &info)) { |
2859 | - msg("[%02lu] xtrabackup: Error: " |
2860 | + msg("[%02u] xtrabackup: Error: " |
2861 | "failed to write meta info for %s\n", |
2862 | cursor->thread_n, cursor->path); |
2863 | return(FALSE); |
2864 | @@ -234,88 +218,3 @@ |
2865 | |
2866 | return(TRUE); |
2867 | } |
2868 | - |
2869 | -/************************************************************************ |
2870 | -Initialize the compact page write filter. |
2871 | - |
2872 | -@return TRUE on success, FALSE on error. */ |
2873 | -static my_bool |
2874 | -wf_compact_init(xb_write_filt_ctxt_t *ctxt, |
2875 | - char *dst_name __attribute__((unused)), xb_fil_cur_t *cursor) |
2876 | -{ |
2877 | - xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt); |
2878 | - |
2879 | - /* Don't compact the system table space */ |
2880 | - cp->skip = cursor->is_system; |
2881 | - |
2882 | - return(TRUE); |
2883 | -} |
2884 | - |
2885 | -static my_bool |
2886 | -check_if_skip_page(byte *page __attribute__((unused))) |
2887 | -{ |
2888 | - return(FALSE); |
2889 | -} |
2890 | - |
2891 | -/************************************************************************ |
2892 | -Run the next batch of pages through the compact page write filter. |
2893 | - |
2894 | -@return TRUE on success, FALSE on error. */ |
2895 | -static my_bool |
2896 | -wf_compact_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) |
2897 | -{ |
2898 | - xb_fil_cur_t *cursor = ctxt->cursor; |
2899 | - ulint page_size = cursor->page_size; |
2900 | - byte *page; |
2901 | - byte *buf_end; |
2902 | - byte *write_from; |
2903 | - xb_wf_compact_ctxt_t *cp = &(ctxt->u.wf_compact_ctxt); |
2904 | - |
2905 | - if (cp->skip) { |
2906 | - return(!ds_write(dstfile, cursor->buf, cursor->buf_read)); |
2907 | - } |
2908 | - |
2909 | - write_from = NULL; |
2910 | - buf_end = cursor->buf + cursor->buf_read; |
2911 | - for (page = cursor->buf; page < buf_end; page += page_size) { |
2912 | - if (!check_if_skip_page(page)) { |
2913 | - if (write_from == NULL) { |
2914 | - write_from = page; |
2915 | - } |
2916 | - continue; |
2917 | - } |
2918 | - } |
2919 | - |
2920 | - /* Write the remaining pages in the buffer, if any */ |
2921 | - if (write_from != NULL && |
2922 | - ds_write(dstfile, write_from, buf_end - write_from)) { |
2923 | - return(FALSE); |
2924 | - } |
2925 | - |
2926 | - return(TRUE); |
2927 | -} |
2928 | - |
2929 | -/************************************************************************ |
2930 | -Close the compact write filter's page map stream. |
2931 | - |
2932 | -@return TRUE on success, FALSE on error. */ |
2933 | -static my_bool |
2934 | -wf_compact_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) |
2935 | -{ |
2936 | - xb_fil_cur_t *cursor = ctxt->cursor; |
2937 | - ulint page_size = cursor->page_size; |
2938 | - xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); |
2939 | - |
2940 | - if (cp->npages != page_size / 4) { |
2941 | - mach_write_to_4(cp->delta_buf + cp->npages * 4, 0xFFFFFFFFUL); |
2942 | - } |
2943 | - |
2944 | - mach_write_to_4(cp->delta_buf, 0x58545241UL); /*"XTRA"*/ |
2945 | - |
2946 | - /* flush buffer */ |
2947 | - if (ds_write(dstfile, cp->delta_buf, cp->npages * page_size)) { |
2948 | - return(FALSE); |
2949 | - } |
2950 | - |
2951 | - return(TRUE); |
2952 | -} |
2953 | |
2954 | === modified file 'src/write_filt.h' |
2955 | --- src/write_filt.h 2013-01-11 13:00:50 +0000 |
2956 | +++ src/write_filt.h 2013-01-14 11:06:22 +0000 |
2957 | @@ -27,6 +27,7 @@ |
2958 | |
2959 | #include "fil_cur.h" |
2960 | #include "datasink.h" |
2961 | +#include "compact.h" |
2962 | |
2963 | /* Incremental page filter context */ |
2964 | typedef struct { |
2965 | @@ -35,11 +36,6 @@ |
2966 | ulint npages; |
2967 | } xb_wf_incremental_ctxt_t; |
2968 | |
2969 | -/* Compact page filter context */ |
2970 | -typedef struct { |
2971 | - my_bool skip; |
2972 | -} xb_wf_compact_ctxt_t; |
2973 | - |
2974 | /* Page filter context used as an opaque structure by callers */ |
2975 | typedef struct { |
2976 | xb_fil_cur_t *cursor; |
2977 | |
2978 | === added file 'src/xb0xb.h' |
2979 | --- src/xb0xb.h 1970-01-01 00:00:00 +0000 |
2980 | +++ src/xb0xb.h 2013-01-14 11:06:22 +0000 |
2981 | @@ -0,0 +1,40 @@ |
2982 | +/****************************************************** |
2983 | +Copyright (c) 2012 Percona Ireland Ltd. |
2984 | + |
2985 | +Declarations of XtraBackup functions called by InnoDB code. |
2986 | + |
2987 | +This program is free software; you can redistribute it and/or modify |
2988 | +it under the terms of the GNU General Public License as published by |
2989 | +the Free Software Foundation; version 2 of the License. |
2990 | + |
2991 | +This program is distributed in the hope that it will be useful, |
2992 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
2993 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2994 | +GNU General Public License for more details. |
2995 | + |
2996 | +You should have received a copy of the GNU General Public License |
2997 | +along with this program; if not, write to the Free Software |
2998 | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
2999 | + |
3000 | +*******************************************************/ |
3001 | + |
3002 | +#ifndef xb0xb_h |
3003 | +#define xb0xb_h |
3004 | + |
3005 | +extern ibool srv_compact_backup; |
3006 | +extern ibool srv_rebuild_indexes; |
3007 | + |
3008 | +/****************************************************************************** |
3009 | +Callback used in buf_page_io_complete() to detect compacted pages. |
3010 | +@return TRUE if the page is marked as compacted, FALSE otherwise. */ |
3011 | +ibool |
3012 | +buf_page_is_compacted( |
3013 | +/*==================*/ |
3014 | + const byte* page); /*!< in: a database page */ |
3015 | + |
3016 | +/****************************************************************************** |
3017 | +Rebuild all secondary indexes in all tables in separate spaces. Called from |
3018 | +innobase_start_or_create_for_mysql(). */ |
3019 | +void |
3020 | +xb_compact_rebuild_indexes(void); |
3021 | +#endif |
3022 | |
3023 | === modified file 'src/xbstream.c' |
3024 | --- src/xbstream.c 2013-01-11 13:00:50 +0000 |
3025 | +++ src/xbstream.c 2013-01-14 11:06:22 +0000 |
3026 | @@ -36,11 +36,12 @@ |
3027 | RUN_MODE_EXTRACT |
3028 | } run_mode_t; |
3029 | |
3030 | -/* Need the following definitions to avoid linking with ds_stream.o, |
3031 | -ds_compress.o, ds_tmpfile.o and their linking dependencies */ |
3032 | +/* Need the following definitions to avoid linking with ds_*.o and their link |
3033 | +dependencies */ |
3034 | datasink_t datasink_stream; |
3035 | datasink_t datasink_compress; |
3036 | datasink_t datasink_tmpfile; |
3037 | +datasink_t datasink_buffer; |
3038 | |
3039 | static run_mode_t opt_mode; |
3040 | static char * opt_directory = NULL; |
3041 | |
3042 | === modified file 'src/xtrabackup.c' |
3043 | --- src/xtrabackup.c 2013-01-14 04:42:47 +0000 |
3044 | +++ src/xtrabackup.c 2013-01-14 11:06:22 +0000 |
3045 | @@ -199,7 +199,6 @@ |
3046 | long innobase_lock_wait_timeout = 50; |
3047 | long innobase_log_buffer_size = 1024*1024L; |
3048 | long innobase_log_files_in_group = 2; |
3049 | -long innobase_log_files_in_group_backup; |
3050 | long innobase_mirrored_log_groups = 1; |
3051 | long innobase_open_files = 300L; |
3052 | |
3053 | @@ -213,7 +212,6 @@ |
3054 | |
3055 | longlong innobase_buffer_pool_size = 8*1024*1024L; |
3056 | longlong innobase_log_file_size = 5*1024*1024L; |
3057 | -longlong innobase_log_file_size_backup; |
3058 | |
3059 | /* The default values for the following char* start-up parameters |
3060 | are determined in innobase_init below: */ |
3061 | @@ -222,7 +220,6 @@ |
3062 | char* innobase_data_home_dir = NULL; |
3063 | char* innobase_data_file_path = NULL; |
3064 | char* innobase_log_group_home_dir = NULL; |
3065 | -char* innobase_log_group_home_dir_backup = NULL; |
3066 | char* innobase_log_arch_dir = NULL;/* unused */ |
3067 | /* The following has a misleading name: starting from 4.0.5, this also |
3068 | affects Windows: */ |
3069 | @@ -252,13 +249,20 @@ |
3070 | #define INNOBASE_WAKE_INTERVAL 32 |
3071 | ulong innobase_active_counter = 0; |
3072 | |
3073 | +ibool srv_compact_backup = FALSE; |
3074 | +ibool srv_rebuild_indexes = FALSE; |
3075 | + |
3076 | static char *xtrabackup_debug_sync = NULL; |
3077 | |
3078 | static my_bool xtrabackup_compact = FALSE; |
3079 | - |
3080 | -/* Datasinks */ |
3081 | -static ds_ctxt_t *ds_data = NULL; |
3082 | -static ds_ctxt_t *ds_meta = NULL; |
3083 | +static my_bool xtrabackup_rebuild_indexes = FALSE; |
3084 | + |
3085 | +/* datasink chain used to store datafiles */ |
3086 | +ds_ctxt_t *ds_data = NULL; |
3087 | +/* datasink chain used to store XtraBackup metainfo files */ |
3088 | +ds_ctxt_t *ds_meta = NULL; |
3089 | + |
3090 | +/* datasinks used to build the above two chains */ |
3091 | static ds_ctxt_t *ds_local = NULL; |
3092 | static ds_ctxt_t *ds_compress = NULL; |
3093 | static ds_ctxt_t *ds_tmpfile = NULL; |
3094 | @@ -266,15 +270,6 @@ |
3095 | static ds_ctxt_t *ds_buffer = NULL; |
3096 | |
3097 | /* ======== Datafiles iterator ======== */ |
3098 | -typedef struct { |
3099 | - fil_system_t *system; |
3100 | - fil_space_t *space; |
3101 | - fil_node_t *node; |
3102 | - ibool started; |
3103 | - os_mutex_t mutex; |
3104 | -} datafiles_iter_t; |
3105 | - |
3106 | -static |
3107 | datafiles_iter_t * |
3108 | datafiles_iter_new(fil_system_t *f_system) |
3109 | { |
3110 | @@ -291,7 +286,6 @@ |
3111 | return it; |
3112 | } |
3113 | |
3114 | -static |
3115 | fil_node_t * |
3116 | datafiles_iter_next(datafiles_iter_t *it) |
3117 | { |
3118 | @@ -329,7 +323,6 @@ |
3119 | return new_node; |
3120 | } |
3121 | |
3122 | -static |
3123 | void |
3124 | datafiles_iter_free(datafiles_iter_t *it) |
3125 | { |
3126 | @@ -421,6 +414,7 @@ |
3127 | OPT_INNODB_THREAD_SLEEP_DELAY, |
3128 | OPT_XTRA_DEBUG_SYNC, |
3129 | OPT_XTRA_COMPACT, |
3130 | + OPT_XTRA_REBUILD_INDEXES, |
3131 | OPT_DEFAULTS_GROUP |
3132 | }; |
3133 | |
3134 | @@ -714,6 +708,12 @@ |
3135 | (G_PTR*) &xtrabackup_compact, (G_PTR*) &xtrabackup_compact, |
3136 | 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, |
3137 | |
3138 | + {"rebuild_indexes", OPT_XTRA_REBUILD_INDEXES, |
3139 | + "Rebuild secondary indexes in InnoDB tables after applying the log. " |
3140 | + "Only has effect with --prepare.", |
3141 | + (G_PTR*) &xtrabackup_rebuild_indexes, (G_PTR*) &xtrabackup_rebuild_indexes, |
3142 | + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, |
3143 | + |
3144 | {"defaults_group", OPT_DEFAULTS_GROUP, "defaults group in config file (default \"mysqld\").", |
3145 | (G_PTR*) &defaults_group, (G_PTR*) &defaults_group, |
3146 | 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
3147 | @@ -1303,8 +1303,9 @@ |
3148 | my_bool |
3149 | xtrabackup_read_metadata(char *filename) |
3150 | { |
3151 | - FILE *fp; |
3152 | - my_bool r = TRUE; |
3153 | + FILE *fp; |
3154 | + my_bool r = TRUE; |
3155 | + int t; |
3156 | |
3157 | fp = fopen(filename,"r"); |
3158 | if(!fp) { |
3159 | @@ -1331,7 +1332,12 @@ |
3160 | != 1) { |
3161 | metadata_last_lsn = 0; |
3162 | } |
3163 | - |
3164 | + /* Optional field */ |
3165 | + if (fscanf(fp, "compact = %d\n", &t) == 1) { |
3166 | + xtrabackup_compact = (t == 1); |
3167 | + } else { |
3168 | + xtrabackup_compact = 0; |
3169 | + } |
3170 | end: |
3171 | fclose(fp); |
3172 | |
3173 | @@ -1348,11 +1354,13 @@ |
3174 | "backup_type = %s\n" |
3175 | "from_lsn = %llu\n" |
3176 | "to_lsn = %llu\n" |
3177 | - "last_lsn = %llu\n", |
3178 | + "last_lsn = %llu\n" |
3179 | + "compact = %d\n", |
3180 | metadata_type, |
3181 | metadata_from_lsn, |
3182 | metadata_to_lsn, |
3183 | - metadata_last_lsn); |
3184 | + metadata_last_lsn, |
3185 | + xtrabackup_compact == TRUE); |
3186 | } |
3187 | |
3188 | /*********************************************************************** |
3189 | @@ -3677,11 +3685,6 @@ |
3190 | os_file_close(src_file); |
3191 | src_file = XB_FILE_UNDEFINED; |
3192 | |
3193 | - /* Backup log parameters */ |
3194 | - innobase_log_group_home_dir_backup = innobase_log_group_home_dir; |
3195 | - innobase_log_file_size_backup = innobase_log_file_size; |
3196 | - innobase_log_files_in_group_backup = innobase_log_files_in_group; |
3197 | - |
3198 | /* fake InnoDB */ |
3199 | innobase_log_group_home_dir = NULL; |
3200 | innobase_log_file_size = file_size; |
3201 | @@ -4236,11 +4239,6 @@ |
3202 | if (!xtrabackup_logfile_is_renamed) |
3203 | return(FALSE); |
3204 | |
3205 | - /* Restore log parameters */ |
3206 | - innobase_log_group_home_dir = innobase_log_group_home_dir_backup; |
3207 | - innobase_log_file_size = innobase_log_file_size_backup; |
3208 | - innobase_log_files_in_group = innobase_log_files_in_group_backup; |
3209 | - |
3210 | /* rename 'ib_logfile0' to 'xtrabackup_logfile' */ |
3211 | if(!xtrabackup_incremental_dir) { |
3212 | sprintf(dst_path, "%s/ib_logfile0", xtrabackup_target_dir); |
3213 | @@ -4308,6 +4306,10 @@ |
3214 | xtrabackup_prepare_func(void) |
3215 | { |
3216 | ulint err; |
3217 | + datafiles_iter_t *it; |
3218 | + fil_node_t *node; |
3219 | + fil_space_t *space; |
3220 | + char metadata_path[FN_REFLEN]; |
3221 | |
3222 | /* cd to target-dir */ |
3223 | |
3224 | @@ -4325,11 +4327,10 @@ |
3225 | |
3226 | /* read metadata of target */ |
3227 | { |
3228 | - char filename[FN_REFLEN]; |
3229 | - |
3230 | - sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME); |
3231 | - |
3232 | - if (!xtrabackup_read_metadata(filename)) |
3233 | + sprintf(metadata_path, "%s/%s", xtrabackup_target_dir, |
3234 | + XTRABACKUP_METADATA_FILENAME); |
3235 | + |
3236 | + if (!xtrabackup_read_metadata(metadata_path)) |
3237 | msg("xtrabackup: error: xtrabackup_read_metadata()\n"); |
3238 | |
3239 | if (!strcmp(metadata_type, "full-backuped")) { |
3240 | @@ -4372,20 +4373,41 @@ |
3241 | os_sync_init(); |
3242 | sync_init(); |
3243 | os_io_init_simple(); |
3244 | + mem_init(srv_mem_pool_size); |
3245 | + |
3246 | if(xtrabackup_init_temp_log()) |
3247 | goto error; |
3248 | |
3249 | - if(innodb_init_param()) |
3250 | + if(innodb_init_param()) { |
3251 | goto error; |
3252 | + } |
3253 | + |
3254 | + /* Expand compacted datafiles */ |
3255 | + |
3256 | + if (xtrabackup_compact) { |
3257 | + srv_compact_backup = TRUE; |
3258 | + |
3259 | + if (!xb_expand_datafiles()) { |
3260 | + goto error; |
3261 | + } |
3262 | + |
3263 | + /* Reset the 'compact' flag in xtrabackup_checkpoints so we |
3264 | + don't expand on subsequent invocations. */ |
3265 | + xtrabackup_compact = FALSE; |
3266 | + if (!xtrabackup_write_metadata(metadata_path)) { |
3267 | + msg("xtrabackup: error: xtrabackup_write_metadata() " |
3268 | + "failed\n"); |
3269 | + goto error; |
3270 | + } |
3271 | + } |
3272 | |
3273 | xb_normalize_init_values(); |
3274 | |
3275 | - mem_init(srv_mem_pool_size); |
3276 | if (xtrabackup_incremental) { |
3277 | err = xb_data_files_init(); |
3278 | if (err != DB_SUCCESS) { |
3279 | - msg("xtrabackup: error: xb_data_files_init() failed with" |
3280 | - "error code %lu\n", err); |
3281 | + msg("xtrabackup: error: xb_data_files_init() failed " |
3282 | + "with error code %lu\n", err); |
3283 | goto error; |
3284 | } |
3285 | |
3286 | @@ -4403,13 +4425,14 @@ |
3287 | os_sync_mutex = NULL; |
3288 | ut_free_all_mem(); |
3289 | |
3290 | - /* check the accessibility of target-dir */ |
3291 | - /* ############# TODO ##################### */ |
3292 | - |
3293 | - if(innodb_init_param()) |
3294 | + /* Reset the configuration as it might have been changed by |
3295 | + xb_data_files_init(). */ |
3296 | + if(innodb_init_param()) { |
3297 | goto error; |
3298 | + } |
3299 | |
3300 | srv_apply_log_only = (ibool) xtrabackup_apply_log_only; |
3301 | + srv_rebuild_indexes = (ibool) xtrabackup_rebuild_indexes; |
3302 | |
3303 | /* increase IO threads */ |
3304 | if(srv_n_file_io_threads < 10) { |
3305 | @@ -4424,214 +4447,199 @@ |
3306 | if(innodb_init()) |
3307 | goto error; |
3308 | |
3309 | - /* align space sizes along with fsp header */ |
3310 | - { |
3311 | - fil_system_t* f_system = fil_system; |
3312 | - fil_space_t* space; |
3313 | - |
3314 | - mutex_enter(&(f_system->mutex)); |
3315 | - space = UT_LIST_GET_FIRST(f_system->space_list); |
3316 | - |
3317 | - while (space != NULL) { |
3318 | - byte* header; |
3319 | - ulint size; |
3320 | - ulint actual_size; |
3321 | - mtr_t mtr; |
3322 | - buf_block_t* block; |
3323 | - ulint flags; |
3324 | - |
3325 | - if (space->purpose == FIL_TABLESPACE) { |
3326 | - mutex_exit(&(f_system->mutex)); |
3327 | - |
3328 | - mtr_start(&mtr); |
3329 | - |
3330 | - mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr); |
3331 | - |
3332 | - block = buf_page_get(space->id, |
3333 | - dict_table_flags_to_zip_size(flags), |
3334 | - 0, RW_S_LATCH, &mtr); |
3335 | - header = FIL_PAGE_DATA /*FSP_HEADER_OFFSET*/ |
3336 | - + buf_block_get_frame(block); |
3337 | - |
3338 | - size = mtr_read_ulint(header + 8 /* FSP_SIZE */, MLOG_4BYTES, &mtr); |
3339 | - |
3340 | - mtr_commit(&mtr); |
3341 | - |
3342 | - fil_extend_space_to_desired_size(&actual_size, space->id, size); |
3343 | - |
3344 | - mutex_enter(&(f_system->mutex)); |
3345 | + it = datafiles_iter_new(fil_system); |
3346 | + if (it == NULL) { |
3347 | + msg("xtrabackup: Error: datafiles_iter_new() failed.\n"); |
3348 | + exit(EXIT_FAILURE); |
3349 | + } |
3350 | + |
3351 | + while ((node = datafiles_iter_next(it)) != NULL) { |
3352 | + byte *header; |
3353 | + ulint size; |
3354 | + ulint actual_size; |
3355 | + mtr_t mtr; |
3356 | + buf_block_t *block; |
3357 | + ulint flags; |
3358 | + |
3359 | + space = node->space; |
3360 | + |
3361 | + /* Align space sizes along with fsp header. We want to process |
3362 | + each space once, so skip all nodes except the first one in a |
3363 | + multi-node space. */ |
3364 | + if (UT_LIST_GET_PREV(chain, node) != NULL) { |
3365 | + continue; |
3366 | } |
3367 | |
3368 | - space = UT_LIST_GET_NEXT(space_list, space); |
3369 | - } |
3370 | - |
3371 | - mutex_exit(&(f_system->mutex)); |
3372 | - } |
3373 | - |
3374 | - |
3375 | + mtr_start(&mtr); |
3376 | + |
3377 | + mtr_s_lock(fil_space_get_latch(space->id, &flags), &mtr); |
3378 | + |
3379 | + block = buf_page_get(space->id, |
3380 | + dict_table_flags_to_zip_size(flags), |
3381 | + 0, RW_S_LATCH, &mtr); |
3382 | + header = FSP_HEADER_OFFSET + buf_block_get_frame(block); |
3383 | + |
3384 | + size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, |
3385 | + &mtr); |
3386 | + |
3387 | + mtr_commit(&mtr); |
3388 | + |
3389 | + fil_extend_space_to_desired_size(&actual_size, space->id, size); |
3390 | + } |
3391 | + |
3392 | + datafiles_iter_free(it); |
3393 | |
3394 | if (xtrabackup_export) { |
3395 | msg("xtrabackup: export option is specified.\n"); |
3396 | - if (innobase_file_per_table) { |
3397 | - fil_system_t* f_system = fil_system; |
3398 | - fil_space_t* space; |
3399 | - fil_node_t* node; |
3400 | - os_file_t info_file = XB_FILE_UNDEFINED; |
3401 | - char info_file_path[FN_REFLEN]; |
3402 | - ibool success; |
3403 | - char table_name[FN_REFLEN]; |
3404 | - |
3405 | - byte* page; |
3406 | - byte* buf = NULL; |
3407 | - |
3408 | - buf = ut_malloc(UNIV_PAGE_SIZE * 2); |
3409 | - page = ut_align(buf, UNIV_PAGE_SIZE); |
3410 | - |
3411 | - /* flush insert buffer at shutdwon */ |
3412 | - innobase_fast_shutdown = 0; |
3413 | - |
3414 | - mutex_enter(&(f_system->mutex)); |
3415 | - |
3416 | - space = UT_LIST_GET_FIRST(f_system->space_list); |
3417 | - while (space != NULL) { |
3418 | - /* treat file_per_table only */ |
3419 | - if (space->purpose != FIL_TABLESPACE |
3420 | - || trx_sys_sys_space(space->id)) |
3421 | - { |
3422 | - space = UT_LIST_GET_NEXT(space_list, space); |
3423 | - continue; |
3424 | - } |
3425 | - |
3426 | - node = UT_LIST_GET_FIRST(space->chain); |
3427 | - while (node != NULL) { |
3428 | - int len; |
3429 | - char *next, *prev, *p; |
3430 | - dict_table_t* table; |
3431 | - dict_index_t* index; |
3432 | - ulint n_index; |
3433 | - |
3434 | - /* node exist == file exist, here */ |
3435 | - strncpy(info_file_path, node->name, FN_REFLEN); |
3436 | - len = strlen(info_file_path); |
3437 | - info_file_path[len - 3] = 'e'; |
3438 | - info_file_path[len - 2] = 'x'; |
3439 | - info_file_path[len - 1] = 'p'; |
3440 | - |
3441 | - p = info_file_path; |
3442 | - prev = NULL; |
3443 | - while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL) |
3444 | - { |
3445 | - prev = p; |
3446 | - p = next + 1; |
3447 | - } |
3448 | - info_file_path[len - 4] = 0; |
3449 | - strncpy(table_name, prev, FN_REFLEN); |
3450 | - |
3451 | - info_file_path[len - 4] = '.'; |
3452 | - |
3453 | - mutex_exit(&(f_system->mutex)); |
3454 | - mutex_enter(&(dict_sys->mutex)); |
3455 | - |
3456 | - table = dict_table_get_low(table_name); |
3457 | - if (!table) { |
3458 | - msg("xtrabackup: error: " |
3459 | - "cannot find dictionary " |
3460 | - "record of table %s\n", |
3461 | - table_name); |
3462 | - goto next_node; |
3463 | - } |
3464 | - index = dict_table_get_first_index(table); |
3465 | - n_index = UT_LIST_GET_LEN(table->indexes); |
3466 | - if (n_index > 31) { |
3467 | - msg("xtrabackup: error: " |
3468 | - "sorry, cannot export over " |
3469 | - "31 indexes for now.\n"); |
3470 | - goto next_node; |
3471 | - } |
3472 | - |
3473 | - /* init exp file */ |
3474 | - bzero(page, UNIV_PAGE_SIZE); |
3475 | - mach_write_to_4(page , 0x78706f72UL); |
3476 | - mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/ |
3477 | - mach_write_to_4(page + 8, n_index); |
3478 | - strncpy((char *) page + 12, |
3479 | - table_name, 500); |
3480 | - |
3481 | - msg("xtrabackup: export metadata of " |
3482 | - "table '%s' to file `%s` " |
3483 | - "(%lu indexes)\n", |
3484 | - table_name, info_file_path, |
3485 | - n_index); |
3486 | - |
3487 | - n_index = 1; |
3488 | - while (index) { |
3489 | - mach_write_to_8(page + n_index * 512, index->id); |
3490 | - mach_write_to_4(page + n_index * 512 + 8, |
3491 | -#if (MYSQL_VERSION_ID < 50100) |
3492 | - index->tree->page); |
3493 | -#else /* MYSQL_VERSION_ID < 51000 */ |
3494 | - index->page); |
3495 | -#endif |
3496 | - strncpy((char *) page + n_index * 512 + |
3497 | - 12, index->name, 500); |
3498 | - |
3499 | - msg("xtrabackup: name=%s, " |
3500 | - "id.low=%lu, page=%lu\n", |
3501 | - index->name, |
3502 | -#if (MYSQL_VERSION_ID < 50500) |
3503 | - index->id.low, |
3504 | -#else |
3505 | - (ulint)(index->id & |
3506 | - 0xFFFFFFFFUL), |
3507 | -#endif |
3508 | -#if (MYSQL_VERSION_ID < 50100) |
3509 | - index->tree->page |
3510 | -#else /* MYSQL_VERSION_ID < 51000 */ |
3511 | - (ulint) index->page |
3512 | + os_file_t info_file = XB_FILE_UNDEFINED; |
3513 | + char info_file_path[FN_REFLEN]; |
3514 | + ibool success; |
3515 | + char table_name[FN_REFLEN]; |
3516 | + |
3517 | + byte* page; |
3518 | + byte* buf = NULL; |
3519 | + |
3520 | + buf = ut_malloc(UNIV_PAGE_SIZE * 2); |
3521 | + page = ut_align(buf, UNIV_PAGE_SIZE); |
3522 | + |
3523 | + /* flush insert buffer at shutdwon */ |
3524 | + innobase_fast_shutdown = 0; |
3525 | + |
3526 | + it = datafiles_iter_new(fil_system); |
3527 | + if (it == NULL) { |
3528 | + msg("xtrabackup: Error: datafiles_iter_new() " |
3529 | + "failed.\n"); |
3530 | + exit(EXIT_FAILURE); |
3531 | + } |
3532 | + while ((node = datafiles_iter_next(it)) != NULL) { |
3533 | + int len; |
3534 | + char *next, *prev, *p; |
3535 | + dict_table_t* table; |
3536 | + dict_index_t* index; |
3537 | + ulint n_index; |
3538 | + |
3539 | + space = node->space; |
3540 | + |
3541 | + /* treat file_per_table only */ |
3542 | + if (trx_sys_sys_space(space->id)) { |
3543 | + continue; |
3544 | + } |
3545 | + |
3546 | + /* node exist == file exist, here */ |
3547 | + strncpy(info_file_path, node->name, FN_REFLEN); |
3548 | + len = strlen(info_file_path); |
3549 | + info_file_path[len - 3] = 'e'; |
3550 | + info_file_path[len - 2] = 'x'; |
3551 | + info_file_path[len - 1] = 'p'; |
3552 | + |
3553 | + p = info_file_path; |
3554 | + prev = NULL; |
3555 | + while ((next = strstr(p, SRV_PATH_SEPARATOR_STR)) != NULL) |
3556 | + { |
3557 | + prev = p; |
3558 | + p = next + 1; |
3559 | + } |
3560 | + info_file_path[len - 4] = 0; |
3561 | + strncpy(table_name, prev, FN_REFLEN); |
3562 | + |
3563 | + info_file_path[len - 4] = '.'; |
3564 | + |
3565 | + mutex_enter(&(dict_sys->mutex)); |
3566 | + |
3567 | + table = dict_table_get_low(table_name); |
3568 | + if (!table) { |
3569 | + msg("xtrabackup: error: " |
3570 | + "cannot find dictionary " |
3571 | + "record of table %s\n", |
3572 | + table_name); |
3573 | + goto next_node; |
3574 | + } |
3575 | + index = dict_table_get_first_index(table); |
3576 | + n_index = UT_LIST_GET_LEN(table->indexes); |
3577 | + if (n_index > 31) { |
3578 | + msg("xtrabackup: error: " |
3579 | + "sorry, cannot export over " |
3580 | + "31 indexes for now.\n"); |
3581 | + goto next_node; |
3582 | + } |
3583 | + |
3584 | + /* init exp file */ |
3585 | + bzero(page, UNIV_PAGE_SIZE); |
3586 | + mach_write_to_4(page , 0x78706f72UL); |
3587 | + mach_write_to_4(page + 4, 0x74696e66UL);/*"xportinf"*/ |
3588 | + mach_write_to_4(page + 8, n_index); |
3589 | + strncpy((char *) page + 12, |
3590 | + table_name, 500); |
3591 | + |
3592 | + msg("xtrabackup: export metadata of " |
3593 | + "table '%s' to file `%s` " |
3594 | + "(%lu indexes)\n", |
3595 | + table_name, info_file_path, |
3596 | + n_index); |
3597 | + |
3598 | + n_index = 1; |
3599 | + while (index) { |
3600 | + mach_write_to_8(page + n_index * 512, index->id); |
3601 | + mach_write_to_4(page + n_index * 512 + 8, |
3602 | +#if (MYSQL_VERSION_ID < 50100) |
3603 | + index->tree->page |
3604 | +#else /* MYSQL_VERSION_ID < 51000 */ |
3605 | + index->page |
3606 | #endif |
3607 | ); |
3608 | - index = dict_table_get_next_index(index); |
3609 | - n_index++; |
3610 | - } |
3611 | - |
3612 | - srv_normalize_path_for_win(info_file_path); |
3613 | - info_file = xb_file_create( |
3614 | - info_file_path, |
3615 | - OS_FILE_OVERWRITE, |
3616 | - OS_FILE_NORMAL, OS_DATA_FILE, |
3617 | - &success); |
3618 | - if (!success) { |
3619 | - os_file_get_last_error(TRUE); |
3620 | - goto next_node; |
3621 | - } |
3622 | - success = os_file_write(info_file_path, info_file, page, |
3623 | - 0, 0, UNIV_PAGE_SIZE); |
3624 | - if (!success) { |
3625 | - os_file_get_last_error(TRUE); |
3626 | - goto next_node; |
3627 | - } |
3628 | - success = xb_file_flush(info_file); |
3629 | - if (!success) { |
3630 | - os_file_get_last_error(TRUE); |
3631 | - goto next_node; |
3632 | - } |
3633 | + strncpy((char *) page + n_index * 512 + |
3634 | + 12, index->name, 500); |
3635 | + |
3636 | + msg("xtrabackup: name=%s, " |
3637 | + "id.low=%lu, page=%lu\n", |
3638 | + index->name, |
3639 | +#if (MYSQL_VERSION_ID < 50500) |
3640 | + index->id.low, |
3641 | +#else |
3642 | + (ulint)(index->id & |
3643 | + 0xFFFFFFFFUL), |
3644 | +#endif |
3645 | +#if (MYSQL_VERSION_ID < 50100) |
3646 | + index->tree->page |
3647 | +#else /* MYSQL_VERSION_ID < 51000 */ |
3648 | + (ulint) index->page |
3649 | +#endif |
3650 | + ); |
3651 | + index = dict_table_get_next_index(index); |
3652 | + n_index++; |
3653 | + |
3654 | + srv_normalize_path_for_win(info_file_path); |
3655 | + info_file = xb_file_create( |
3656 | + info_file_path, |
3657 | + OS_FILE_OVERWRITE, |
3658 | + OS_FILE_NORMAL, OS_DATA_FILE, |
3659 | + &success); |
3660 | + if (!success) { |
3661 | + os_file_get_last_error(TRUE); |
3662 | + goto next_node; |
3663 | + } |
3664 | + success = os_file_write(info_file_path, |
3665 | + info_file, page, |
3666 | + 0, 0, UNIV_PAGE_SIZE); |
3667 | + if (!success) { |
3668 | + os_file_get_last_error(TRUE); |
3669 | + goto next_node; |
3670 | + } |
3671 | + success = xb_file_flush(info_file); |
3672 | + if (!success) { |
3673 | + os_file_get_last_error(TRUE); |
3674 | + goto next_node; |
3675 | + } |
3676 | next_node: |
3677 | - if (info_file != XB_FILE_UNDEFINED) { |
3678 | - os_file_close(info_file); |
3679 | - info_file = XB_FILE_UNDEFINED; |
3680 | - } |
3681 | - mutex_exit(&(dict_sys->mutex)); |
3682 | - mutex_enter(&(f_system->mutex)); |
3683 | - |
3684 | - node = UT_LIST_GET_NEXT(chain, node); |
3685 | + if (info_file != XB_FILE_UNDEFINED) { |
3686 | + os_file_close(info_file); |
3687 | + info_file = XB_FILE_UNDEFINED; |
3688 | } |
3689 | - |
3690 | - space = UT_LIST_GET_NEXT(space_list, space); |
3691 | + mutex_exit(&(dict_sys->mutex)); |
3692 | } |
3693 | - mutex_exit(&(f_system->mutex)); |
3694 | - |
3695 | - ut_free(buf); |
3696 | } |
3697 | + |
3698 | + ut_free(buf); |
3699 | } |
3700 | |
3701 | /* print binlog position (again?) */ |
3702 | @@ -4921,12 +4929,6 @@ |
3703 | exit(EXIT_FAILURE); |
3704 | } |
3705 | |
3706 | - if (xtrabackup_incremental && xtrabackup_compact) { |
3707 | - msg("xtrabackup: error: --compact cannot be used with " |
3708 | - "incremental backups.\n"); |
3709 | - exit(EXIT_FAILURE); |
3710 | - } |
3711 | - |
3712 | if (xtrabackup_incremental && xtrabackup_stream && |
3713 | xtrabackup_stream_fmt == XB_STREAM_FMT_TAR) { |
3714 | msg("xtrabackup: error: " |
3715 | |
3716 | === modified file 'src/xtrabackup.h' |
3717 | --- src/xtrabackup.h 2013-01-11 13:00:50 +0000 |
3718 | +++ src/xtrabackup.h 2013-01-14 11:06:22 +0000 |
3719 | @@ -21,6 +21,8 @@ |
3720 | #ifndef XB_XTRABACKUP_H |
3721 | #define XB_XTRABACKUP_H |
3722 | |
3723 | +#include "datasink.h" |
3724 | + |
3725 | typedef struct { |
3726 | ulint page_size; |
3727 | ulint zip_size; |
3728 | @@ -33,13 +35,39 @@ |
3729 | XB_STREAM_FMT_XBSTREAM |
3730 | } xb_stream_fmt_t; |
3731 | |
3732 | +/* ======== Datafiles iterator ======== */ |
3733 | +typedef struct { |
3734 | + fil_system_t *system; |
3735 | + fil_space_t *space; |
3736 | + fil_node_t *node; |
3737 | + ibool started; |
3738 | + os_mutex_t mutex; |
3739 | +} datafiles_iter_t; |
3740 | + |
3741 | /* value of the --incremental option */ |
3742 | extern LSN64 incremental_lsn; |
3743 | |
3744 | +extern char *xtrabackup_target_dir; |
3745 | +extern ds_ctxt_t *ds_meta; |
3746 | +extern ds_ctxt_t *ds_data; |
3747 | + |
3748 | void xtrabackup_io_throttling(void); |
3749 | my_bool xb_write_delta_metadata(const char *filename, |
3750 | const xb_delta_info_t *info); |
3751 | |
3752 | +datafiles_iter_t *datafiles_iter_new(fil_system_t *f_system); |
3753 | +fil_node_t *datafiles_iter_next(datafiles_iter_t *it); |
3754 | +void datafiles_iter_free(datafiles_iter_t *it); |
3755 | + |
3756 | +/************************************************************************ |
3757 | +Initialize the tablespace memory cache and populate it by scanning for and |
3758 | +opening data files */ |
3759 | +ulint xb_data_files_init(void); |
3760 | + |
3761 | +/************************************************************************ |
3762 | +Destroy the tablespace memory cache. */ |
3763 | +void xb_data_files_close(void); |
3764 | + |
3765 | /*********************************************************************** |
3766 | Reads the space flags from a given data file and returns the compressed |
3767 | page size, or 0 if the space is not compressed. */ |
3768 | |
3769 | === added file 'test/disabled/workaround_for_lp855155' |
3770 | === modified file 'test/inc/incremental_sample-db/incremental_sample-schema.sql' |
3771 | --- test/inc/incremental_sample-db/incremental_sample-schema.sql 2011-07-05 04:17:41 +0000 |
3772 | +++ test/inc/incremental_sample-db/incremental_sample-schema.sql 2013-01-14 11:06:22 +0000 |
3773 | @@ -1,5 +1,6 @@ |
3774 | DROP TABLE IF EXISTS `test`; |
3775 | CREATE TABLE `test` ( |
3776 | - `a` int(11) DEFAULT NULL, |
3777 | - `number` int(11) DEFAULT NULL |
3778 | + `a` int(11) NOT NULL PRIMARY KEY, |
3779 | + `number` int(11) DEFAULT NULL, |
3780 | + KEY(number) |
3781 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; |
3782 | |
3783 | === renamed file 'test/disabled/compact.sh' => 'test/t/compact.sh' |
3784 | --- test/disabled/compact.sh 2012-02-16 18:02:07 +0000 |
3785 | +++ test/t/compact.sh 2013-01-14 11:06:22 +0000 |
3786 | @@ -4,8 +4,7 @@ |
3787 | |
3788 | . inc/common.sh |
3789 | |
3790 | -init |
3791 | -run_mysqld --innodb_file_per_table |
3792 | +start_server --innodb_file_per_table |
3793 | load_dbase_schema sakila |
3794 | load_dbase_data sakila |
3795 | |
3796 | @@ -16,20 +15,20 @@ |
3797 | |
3798 | record_db_state sakila |
3799 | |
3800 | -stop_mysqld |
3801 | +stop_server |
3802 | |
3803 | # Remove datadir |
3804 | rm -r $mysql_datadir |
3805 | |
3806 | # Restore sakila |
3807 | -vlog "Applying log" |
3808 | -innobackupex --apply-log $backup_dir |
3809 | + |
3810 | +innobackupex --apply-log --rebuild-indexes $backup_dir |
3811 | |
3812 | vlog "Restoring MySQL datadir" |
3813 | mkdir -p $mysql_datadir |
3814 | innobackupex --copy-back $backup_dir |
3815 | |
3816 | -run_mysqld |
3817 | +start_server |
3818 | |
3819 | verify_db_state sakila |
3820 | |
3821 | |
3822 | === renamed file 'test/disabled/compact_compressed.sh' => 'test/t/compact_compressed.sh' |
3823 | --- test/disabled/compact_compressed.sh 2012-02-16 18:02:07 +0000 |
3824 | +++ test/t/compact_compressed.sh 2013-01-14 11:06:22 +0000 |
3825 | @@ -4,8 +4,6 @@ |
3826 | |
3827 | . inc/common.sh |
3828 | |
3829 | -init |
3830 | - |
3831 | if [ -z "$INNODB_VERSION" ]; then |
3832 | echo "Requires InnoDB plugin or XtraDB" >$SKIPPED_REASON |
3833 | exit $SKIPPED_EXIT_CODE |
3834 | @@ -17,37 +15,63 @@ |
3835 | --innodb_file_format=Barracuda" |
3836 | |
3837 | # |
3838 | -# Test compact backup of a compressed tablespace with a specific page size |
3839 | +# Test compact backup of a compressed tablespace with a specific page size |
3840 | # |
3841 | function test_compact_compressed() |
3842 | { |
3843 | - page_size=$1 |
3844 | + local page_size=$1 |
3845 | + local backup_dir |
3846 | |
3847 | echo "************************************************************************" |
3848 | echo "Testing compact backup with compressed page size=${page_size}KB " |
3849 | echo "************************************************************************" |
3850 | |
3851 | - run_mysqld ${mysqld_additional_args} |
3852 | + start_server ${mysqld_additional_args} |
3853 | |
3854 | load_dbase_schema sakila |
3855 | load_dbase_data sakila |
3856 | |
3857 | + backup_dir="$topdir/backup" |
3858 | + |
3859 | vlog "Compressing tables" |
3860 | |
3861 | table_list=`${MYSQL} ${MYSQL_ARGS} -Ns -e \ |
3862 | "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='sakila' \ |
3863 | -AND TABLE_TYPE='BASE TABLE'"` |
3864 | +AND TABLE_TYPE='BASE TABLE' AND ENGINE='InnoDB'"` |
3865 | |
3866 | for t in $table_list; do |
3867 | run_cmd ${MYSQL} ${MYSQL_ARGS} -e \ |
3868 | "ALTER TABLE $t ENGINE=InnoDB ROW_FORMAT=compressed \ |
3869 | KEY_BLOCK_SIZE=$page_size" sakila |
3870 | done |
3871 | + |
3872 | + innobackupex --no-timestamp --compact $backup_dir |
3873 | + record_db_state sakila |
3874 | + |
3875 | + stop_server |
3876 | + |
3877 | + rm -r $mysql_datadir |
3878 | + |
3879 | + innobackupex --apply-log --rebuild-indexes $backup_dir |
3880 | + |
3881 | + vlog "Restoring MySQL datadir" |
3882 | + mkdir -p $mysql_datadir |
3883 | + innobackupex --copy-back $backup_dir |
3884 | + |
3885 | + start_server |
3886 | + |
3887 | + verify_db_state sakila |
3888 | + |
3889 | + stop_server |
3890 | + clean |
3891 | } |
3892 | |
3893 | -for page_size in 1 2 4 8 16; do |
3894 | - init |
3895 | + |
3896 | +# Cannot test with lower page sizes, because not all tables can be compressed |
3897 | +# with KEY_BLOCK_SIZE < 8. This can be changed, if we implement 'canned' |
3898 | +# databases in the test suite, which will contain tables compressed with the |
3899 | +# minimum possible page size. |
3900 | +for page_size in 8 16; do |
3901 | test_compact_compressed ${page_size} |
3902 | - clean |
3903 | done |
3904 | |
3905 | |
3906 | === modified file 'test/testrun.sh' |
3907 | --- test/testrun.sh 2013-01-09 22:25:19 +0000 |
3908 | +++ test/testrun.sh 2013-01-14 11:06:22 +0000 |
3909 | @@ -86,9 +86,10 @@ |
3910 | else |
3911 | LD_LIBRARY_PATH=$MYSQL_BASEDIR/lib/mysql:$LD_LIBRARY_PATH |
3912 | fi |
3913 | + DYLD_LIBRARY_PATH="$LD_LIBRARY_PATH" |
3914 | |
3915 | export TEST_BASEDIR PORT_BASE TAR MYSQL_BASEDIR MYSQL MYSQLD MYSQLADMIN \ |
3916 | -MYSQL_INSTALL_DB PATH LD_LIBRARY_PATH |
3917 | +MYSQL_INSTALL_DB PATH LD_LIBRARY_PATH DYLD_LIBRARY_PATH MYSQLDUMP |
3918 | } |
3919 | |
3920 | function get_version_info() |
3921 | |
3922 | === modified file 'utils/build.sh' |
3923 | --- utils/build.sh 2013-01-02 04:23:18 +0000 |
3924 | +++ utils/build.sh 2013-01-14 11:06:22 +0000 |
3925 | @@ -10,26 +10,34 @@ |
3926 | AUTO_DOWNLOAD=${AUTO_DOWNLOAD:-no} |
3927 | MASTER_SITE="http://s3.amazonaws.com/percona.com/downloads/community" |
3928 | |
3929 | +top_dir=`pwd` |
3930 | + |
3931 | # Percona Server 5.5 does not build with -Werror, so ignore DEBUG for now |
3932 | if [ -n "$DEBUG" -a "$1" != "galera55" -a "$1" != "xtradb55" -a "$1" != "xtradb51" -a "$1" != "xtradb" ] |
3933 | then |
3934 | # InnoDB extra debug flags |
3935 | - innodb_extra_debug="-DUNIV_DEBUG -DUNIV_SYNC_DEBUG -DUNIV_MEM_DEBUG \ |
3936 | + innodb_extra_debug="-DUNIV_DEBUG -DUNIV_MEM_DEBUG \ |
3937 | -DUNIV_DEBUG_THREAD_CREATION -DUNIV_DEBUG_LOCK_VALIDATE -DUNIV_DEBUG_PRINT \ |
3938 | -DUNIV_DEBUG_FILE_ACCESS -DUNIV_SEARCH_DEBUG -DUNIV_LOG_LSN_DEBUG \ |
3939 | -DUNIV_ZIP_DEBUG -DUNIV_AHI_DEBUG -DUNIV_SQL_DEBUG -DUNIV_AIO_DEBUG \ |
3940 | -DUNIV_LRU_DEBUG -DUNIV_BUF_DEBUG -DUNIV_HASH_DEBUG -DUNIV_LIST_DEBUG -DUNIV_IBUF_DEBUG" |
3941 | - export CFLAGS="$CFLAGS -g -O0 $innodb_extra_debug -DSAFE_MUTEX -DSAFEMALLOC" |
3942 | - export CXXFLAGS="$CXXFLAGS -g -O0 $innodb_extra_debug -DSAFE_MUTEX -DSAFEMALLOC" |
3943 | + CFLAGS="$CFLAGS -g -O0 $innodb_extra_debug -DSAFE_MUTEX -DSAFEMALLOC" |
3944 | + CXXFLAGS="$CXXFLAGS -g -O0 $innodb_extra_debug -DSAFE_MUTEX -DSAFEMALLOC" |
3945 | extra_config_51="--with-debug=full" |
3946 | extra_config_55="-DWITH_DEBUG=ON" |
3947 | else |
3948 | - export CFLAGS="$CFLAGS -g -O3" |
3949 | - export CXXFLAGS="$CXXFLAGS -g -O3" |
3950 | + CFLAGS="$CFLAGS -g -O3" |
3951 | + CXXFLAGS="$CXXFLAGS -g -O3" |
3952 | extra_config_51= |
3953 | extra_config_55= |
3954 | fi |
3955 | |
3956 | +xtrabackup_include_dir="$top_dir/src" |
3957 | +CFLAGS="$CFLAGS -I$xtrabackup_include_dir" |
3958 | +CXXFLAGS="$CXXFLAGS -I$xtrabackup_include_dir" |
3959 | + |
3960 | +export CFLAGS CXXFLAGS |
3961 | + |
3962 | MAKE_CMD=make |
3963 | if gmake --version > /dev/null 2>&1 |
3964 | then |
3965 | @@ -181,8 +189,6 @@ |
3966 | fi |
3967 | |
3968 | type=$1 |
3969 | -top_dir=`pwd` |
3970 | - |
3971 | |
3972 | case "$type" in |
3973 | "innodb51" | "plugin") |
http:// jenkins. percona. com/view/ XtraBackup/ job/percona- xtrabackup- 2.1-param/ 105/
compact_compressed failures in debug builds is a result of index creating taking too long with all debug options turned on (in particular, UNIV_SYNC_DEBUG).