Merge lp:~gl-az/percona-xtrabackup/BT-32889-history-on-server into lp:percona-xtrabackup/2.1
- BT-32889-history-on-server
- Merge into 2.1
Proposed by
George Ormond Lorch III
Status: | Rejected |
---|---|
Rejected by: | Alexey Kopytov |
Proposed branch: | lp:~gl-az/percona-xtrabackup/BT-32889-history-on-server |
Merge into: | lp:percona-xtrabackup/2.1 |
Diff against target: |
678 lines (+553/-1) 2 files modified
innobackupex (+354/-1) test/t/history_on_server.sh (+199/-0) |
To merge this branch: | bzr merge lp:~gl-az/percona-xtrabackup/BT-32889-history-on-server |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Registry Administrators | Pending | ||
Review via email: mp+184853@code.launchpad.net |
Commit message
Description of the change
BT-32889
Implementation of xtrabackup http://
http://
To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote : | # |
Unmerged revisions
- 676. By George Ormond Lorch III
-
Implementation of xtrabackup http://
blueprints. launchpad. net/percona- xtrabackup/ +spec/history- on-the- server and test case.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'innobackupex' |
2 | --- innobackupex 2013-08-30 09:55:04 +0000 |
3 | +++ innobackupex 2013-09-10 19:03:04 +0000 |
4 | @@ -145,6 +145,10 @@ |
5 | my %mysql; |
6 | my $option_backup = ''; |
7 | |
8 | +my $option_history; |
9 | +my $option_incremental_history_name = ''; |
10 | +my $option_incremental_history_uuid = ''; |
11 | + |
12 | # name of the my.cnf configuration file |
13 | #my $config_file = ''; |
14 | |
15 | @@ -193,6 +197,9 @@ |
16 | # name of the file where slave info is written |
17 | my $slave_info; |
18 | |
19 | +# name of the file where version and backup history is written |
20 | +my $backup_history; |
21 | + |
22 | # mysql binlog position as given by "SHOW MASTER STATUS" command |
23 | my $mysql_binlog_position = ''; |
24 | |
25 | @@ -268,6 +275,11 @@ |
26 | my $copy_dir_overwrite; |
27 | my $copy_dir_resolve_isl; |
28 | |
29 | +# for history on server record |
30 | +my $history_start_time = current_time_mysql(); |
31 | +my $history_lock_time = 0; |
32 | +my $history_delete_checkpoints = 0; |
33 | + |
34 | ###################################################################### |
35 | # program execution begins here |
36 | ###################################################################### |
37 | @@ -404,6 +416,14 @@ |
38 | } |
39 | |
40 | # |
41 | +# return current local time as mysql friendly string in form |
42 | +# "2013-08-27 17:30:00" |
43 | +# |
44 | +sub current_time_mysql { |
45 | + return strftime("%Y-%m-%d %H:%M:%S", localtime()); |
46 | +} |
47 | + |
48 | +# |
49 | # Global initialization: |
50 | # 1. Override the 'die' builtin to customize the format of error messages |
51 | # |
52 | @@ -651,6 +671,37 @@ |
53 | detect_mysql_capabilities_for_backup(\%mysql); |
54 | } |
55 | |
56 | + # |
57 | + # if one of the history incrementals is being used, try to grab the |
58 | + # innodb_to_lsn from the history table and set the option_incremental_lsn |
59 | + # |
60 | + if ($option_incremental && !$option_incremental_lsn) { |
61 | + if ($option_incremental_history_name) { |
62 | + my $query = "SELECT innodb_to_lsn ". |
63 | + "FROM PERCONA_SCHEMA.xtrabackup_history ". |
64 | + "WHERE name = '$option_incremental_history_name' ". |
65 | + "AND innodb_to_lsn IS NOT NULL ". |
66 | + "ORDER BY innodb_to_lsn DESC LIMIT 1"; |
67 | + |
68 | + eval { |
69 | + $option_incremental_lsn = |
70 | + $mysql{dbh}->selectrow_hashref($query)->{innodb_to_lsn}; |
71 | + } || die("Error while attempting to find history record for name ". |
72 | + "'$option_incremental_history_name'\n"); |
73 | + } elsif ($option_incremental_history_uuid) { |
74 | + my $query = "SELECT innodb_to_lsn ". |
75 | + "FROM PERCONA_SCHEMA.xtrabackup_history ". |
76 | + "WHERE uuid = '$option_incremental_history_uuid' ". |
77 | + "AND innodb_to_lsn IS NOT NULL"; |
78 | + |
79 | + eval { |
80 | + $option_incremental_lsn = |
81 | + $mysql{dbh}->selectrow_hashref($query)->{innodb_to_lsn}; |
82 | + } || die("Error while attempting to find history record for uuid ". |
83 | + "'$option_incremental_history_uuid'\n"); |
84 | + } |
85 | + } |
86 | + |
87 | # start ibbackup as a child process |
88 | start_ibbackup(); |
89 | |
90 | @@ -675,6 +726,9 @@ |
91 | # make a prep copy before locking tables, if using rsync |
92 | backup_files(1); |
93 | |
94 | + # start counting how long lock is held for history |
95 | + $history_lock_time = time(); |
96 | + |
97 | # flush tables with read lock |
98 | mysql_lockall(\%mysql); |
99 | |
100 | @@ -708,6 +762,13 @@ |
101 | # release read locks on all tables |
102 | mysql_unlockall(\%mysql) if !$option_no_lock; |
103 | |
104 | + # calculate how long lock was held for history |
105 | + if ($option_no_lock) { |
106 | + $history_lock_time = 0; |
107 | + } else { |
108 | + $history_lock_time = time() - $history_lock_time; |
109 | + } |
110 | + |
111 | my $ibbackup_exit_code = wait_for_ibbackup_finish(); |
112 | |
113 | if ( $option_safe_slave_backup && $sql_thread_started) { |
114 | @@ -731,6 +792,8 @@ |
115 | print STDERR "$prefix MySQL slave binlog position: $mysql_slave_position\n"; |
116 | } |
117 | |
118 | + update_history(\%mysql); |
119 | + |
120 | return $ibbackup_exit_code; |
121 | } |
122 | |
123 | @@ -2242,8 +2305,14 @@ |
124 | $binlog_info = $work_dir . '/xtrabackup_binlog_info'; |
125 | $galera_info = $work_dir . '/xtrabackup_galera_info'; |
126 | $slave_info = $work_dir . '/xtrabackup_slave_info'; |
127 | + $backup_history = $work_dir . '/xtrabackup_history'; |
128 | write_backup_config_file($backup_config_file); |
129 | |
130 | + if (!$option_extra_lsndir && defined($option_history)) { |
131 | + $option_extra_lsndir = $option_tmpdir; |
132 | + $history_delete_checkpoints = 1; |
133 | + } |
134 | + |
135 | foreach (@xb_suspend_files) { |
136 | my $suspend_file = $work_dir . "$_"; |
137 | if ( -e "$suspend_file" ) { |
138 | @@ -2347,6 +2416,7 @@ |
139 | 'encrypt-threads=i' => \$option_encrypt_threads, |
140 | 'encrypt-chunk-size=s' => \$option_encrypt_chunk_size, |
141 | 'help' => \$option_help, |
142 | + 'history:s' => \$option_history, |
143 | 'version' => \$option_version, |
144 | 'throttle=i' => \$option_throttle, |
145 | 'log-copy-interval=i', \$option_log_copy_interval, |
146 | @@ -2374,6 +2444,8 @@ |
147 | 'incremental' => \$option_incremental, |
148 | 'incremental-basedir=s' => \$option_incremental_basedir, |
149 | 'incremental-force-scan' => \$option_incremental_force_scan, |
150 | + 'incremental-history-name=s' => \$option_incremental_history_name, |
151 | + 'incremental-history-uuid=s' => \$option_incremental_history_uuid, |
152 | 'incremental-lsn=s' => \$option_incremental_lsn, |
153 | 'incremental-dir=s' => \$option_incremental_dir, |
154 | 'extra-lsndir=s' => \$option_extra_lsndir, |
155 | @@ -2481,7 +2553,9 @@ |
156 | # we are making a backup, get backup root directory |
157 | $option_backup = "1"; |
158 | $backup_root = $ARGV[0]; |
159 | - if ($option_incremental && !$option_incremental_lsn) { |
160 | + if ($option_incremental && !$option_incremental_lsn && |
161 | + !$option_incremental_history_name && |
162 | + !$option_incremental_history_uuid) { |
163 | if ($option_incremental_basedir) { |
164 | $incremental_basedir = $option_incremental_basedir; |
165 | } else { |
166 | @@ -3448,6 +3522,267 @@ |
167 | 'WHERE PLUGIN_NAME LIKE "INNODB_CHANGED_PAGES"') |
168 | } |
169 | |
170 | +# |
171 | +# scrubs (replaces with ...) the value for the specified option |
172 | +# Example: |
173 | +# scrub_option("--user=fred --password=mypassword", "--password") |
174 | +# returns "--user=fred --password=..." |
175 | +# |
176 | +sub scrub_option { |
177 | + my $scrub = shift; |
178 | + my $command = shift; |
179 | + $scrub = "--$scrub="; |
180 | + |
181 | + my $pos = index($command, $scrub, 0); |
182 | + if ($pos >= 0) { |
183 | + substr($command, $pos, index($command, " ", $pos) - $pos, "$scrub..."); |
184 | + } |
185 | + return $command; |
186 | +} |
187 | + |
188 | +# |
189 | +# Creates PERCONA_SCHEMA.xtrabackup_history and Writes a new history |
190 | +# record to the table containg all the history info particular to the |
191 | +# just completed backup. |
192 | +# |
193 | +sub update_history { |
194 | + my $con = shift; |
195 | + my $tmp; |
196 | + my $uuid; |
197 | + my $insert_vals = ''; |
198 | + my $insert_query = ''; |
199 | + my $file_content = ''; |
200 | + |
201 | + if (!defined($option_history)) { |
202 | + return; |
203 | + } |
204 | + |
205 | + mysql_query($con, "CREATE DATABASE IF NOT EXISTS PERCONA_SCHEMA"); |
206 | + mysql_query($con, "CREATE TABLE IF NOT EXISTS PERCONA_SCHEMA.xtrabackup_history(". |
207 | + "uuid VARCHAR(40) NOT NULL PRIMARY KEY,". |
208 | + "name VARCHAR(255) DEFAULT NULL,". |
209 | + "tool_name VARCHAR(255) DEFAULT NULL,". |
210 | + "tool_command TEXT DEFAULT NULL,". |
211 | + "tool_version VARCHAR(255) DEFAULT NULL,". |
212 | + "ibbackup_version VARCHAR(255) DEFAULT NULL,". |
213 | + "mysql_version VARCHAR(255) DEFAULT NULL,". |
214 | + "start_time TIMESTAMP NULL DEFAULT NULL,". |
215 | + "end_time TIMESTAMP NULL DEFAULT NULL,". |
216 | + "lock_time BIGINT UNSIGNED DEFAULT NULL,". |
217 | + "binlog_pos VARCHAR(128) DEFAULT NULL,". |
218 | + "innodb_from_lsn BIGINT UNSIGNED DEFAULT NULL,". |
219 | + "innodb_to_lsn BIGINT UNSIGNED DEFAULT NULL,". |
220 | + "partial ENUM('Y', 'N') DEFAULT NULL,". |
221 | + "incremental ENUM('Y', 'N') DEFAULT NULL,". |
222 | + "format ENUM('file', 'tar', 'xbstream') DEFAULT NULL,". |
223 | + "compact ENUM('Y', 'N') DEFAULT NULL,". |
224 | + "compressed ENUM('Y', 'N') DEFAULT NULL,". |
225 | + "encrypted ENUM('Y', 'N') DEFAULT NULL". |
226 | + ") ENGINE=innodb"); |
227 | + |
228 | + # uuid |
229 | + # we use the mysql UUID() function to avoid platform dependencies with uuidgen |
230 | + # and Data::UUID. We select uuid here individually here so that it can be |
231 | + # reported to stderr after successful history record insertion |
232 | + $tmp = "SELECT UUID() AS uuid"; |
233 | + eval { |
234 | + $uuid = $mysql{dbh}->selectrow_hashref($tmp)->{uuid}; |
235 | + } || die("Error while attempting to create UUID for history record.\n"); |
236 | + $insert_vals = "'$uuid'"; |
237 | + $file_content = "uuid = $uuid"; |
238 | + |
239 | + # name |
240 | + if ($option_history) { |
241 | + $insert_vals .= ", '$option_history'"; |
242 | + $file_content .= "\nname = $option_history"; |
243 | + } else { |
244 | + $insert_vals .= ", NULL"; |
245 | + $file_content .= "\nname = "; |
246 | + } |
247 | + |
248 | + # tool_name |
249 | + $tmp = basename($0); |
250 | + $insert_vals .= ", '$tmp'"; |
251 | + $file_content .= "\ntool_name = $tmp"; |
252 | + |
253 | + # tool_command |
254 | + # there is probably a better way to do this but at this point ARGV has been |
255 | + # consumed/shifted and I don't think that trying to recompose the command |
256 | + # line from all of the $option_* variables is a great idea, besides, the |
257 | + # purpose of this particular field is mainly for debugging so giving a very |
258 | + # accurate/uninterpreted representation is highly desirable. |
259 | + $tmp = sprintf("cat /proc/%d/cmdline", $$); |
260 | + $tmp = qx($tmp); |
261 | + system("cp /proc/$$/cmdline /tmp"); |
262 | + $tmp =~ s/\0/ /g; # transform embedded nulls between args to spaces |
263 | + |
264 | + # scrub --password, --encrypt, --encrypt-key, and --encrypt-key-file |
265 | + # from tool_command |
266 | + $tmp = scrub_option("password", $tmp); |
267 | + $tmp = scrub_option("encrypt", $tmp); |
268 | + $tmp = scrub_option("encrypt-key", $tmp); |
269 | + $tmp = scrub_option("encrypt-key-file", $tmp); |
270 | + $insert_vals .= ",'$tmp'"; |
271 | + $file_content .="\ntool_command = $tmp"; |
272 | + |
273 | + # tool_version |
274 | + $insert_vals .= ", '$innobackup_version'"; |
275 | + $file_content .= "\ntool_version = $innobackup_version"; |
276 | + |
277 | + # ibbackup_version |
278 | + $tmp = "$option_ibbackup_binary -v 2>&1"; |
279 | + $tmp = qx($tmp); |
280 | + chomp($tmp); |
281 | + $insert_vals .= ", '$tmp'"; |
282 | + $file_content .= "\nibbackup_version = $tmp"; |
283 | + |
284 | + # mysql_version |
285 | + $tmp = |
286 | + $con->{dbh}->selectrow_hashref("SELECT VERSION() as version")->{version}; |
287 | + $insert_vals .= ", '$tmp'"; |
288 | + $file_content .= "\nmysql_version = $tmp"; |
289 | + |
290 | + # start_time |
291 | + $insert_vals .= ", '$history_start_time'"; |
292 | + $file_content .= "\nstart_time = $history_start_time"; |
293 | + |
294 | + # end_time |
295 | + $tmp = current_time_mysql(); |
296 | + $insert_vals .= ", '$tmp'"; |
297 | + $file_content .= "\nend_time = $tmp"; |
298 | + |
299 | + # lock_time |
300 | + $insert_vals .= ", $history_lock_time"; |
301 | + $file_content .= "\nlock_time = $history_lock_time"; |
302 | + |
303 | + # binlog_pos |
304 | + if ($mysql_binlog_position) { |
305 | + $tmp =$mysql_binlog_position; |
306 | + $tmp =~ s/'/\\'/g; # escape single quotes |
307 | + $insert_vals .= ", '$tmp'"; |
308 | + $file_content .= "\nbinlog_pos = $mysql_binlog_position"; |
309 | + } else { |
310 | + $insert_vals .= ", NULL"; |
311 | + $file_content .= "\nbinlog_pos = "; |
312 | + } |
313 | + |
314 | + # innodb_from_lsn |
315 | + # grab the from_lsn from the extra checkpoints file, parse and delete it |
316 | + # if necessary. This could generate an error if the checkpoints file |
317 | + # isn't 100% correct in the format. |
318 | + $tmp = "cat $option_extra_lsndir/xtrabackup_checkpoints | grep from_lsn"; |
319 | + $tmp = qx($tmp); |
320 | + chomp($tmp); |
321 | + substr($tmp, 0, 11, ""); # strip "from_lsn = " |
322 | + if (length $tmp) { |
323 | + $insert_vals .= ", $tmp"; |
324 | + $file_content .= "\ninnodb_from_lsn = $tmp"; |
325 | + } else { |
326 | + print STDERR "WARNING : Unable to obtain from_lsn from " . |
327 | + "$option_extra_lsndir/xtrabackup_checkpoints, " . |
328 | + "writing NULL to history record.\n"; |
329 | + $insert_vals .= ", NULL"; |
330 | + $file_content .= "\ninnodb_from_lsn = "; |
331 | + } |
332 | + |
333 | + # innodb_to_lsn |
334 | + # grab the to_lsn from the extra checkpoints file, parse and delete it |
335 | + # if necessary. This could generate an error if the checkpoints file |
336 | + # isn't 100% correct in the format. |
337 | + $tmp = "cat $option_extra_lsndir/xtrabackup_checkpoints | grep to_lsn"; |
338 | + $tmp = qx($tmp); |
339 | + chomp($tmp); |
340 | + substr($tmp, 0, 9, ""); # strip "to_lsn = " |
341 | + if (length $tmp) { |
342 | + $insert_vals .= ", $tmp"; |
343 | + $file_content .= "\ninnodb_to_lsn = $tmp"; |
344 | + } else { |
345 | + print STDERR "WARNING : Unable to obtain to_lsn from " . |
346 | + "$option_extra_lsndir/xtrabackup_checkpoints, " . |
347 | + "writing NULL to history record.\n"; |
348 | + $insert_vals .= ", NULL"; |
349 | + $file_content .= "\ninnodb_to_lsn = "; |
350 | + } |
351 | + |
352 | + # we're finished with the checkpoints file, delete it if it was a temp |
353 | + # only for the history |
354 | + if ($history_delete_checkpoints > 0) { |
355 | + system("rm -f $option_extra_lsndir/xtrabackup_checkpoints"); |
356 | + } |
357 | + |
358 | + # partial (Y | N) |
359 | + if ($option_include || $option_databases || $option_tables_file || $option_export) { |
360 | + $insert_vals .= ", 'Y'"; |
361 | + $file_content .= "\npartial = Y"; |
362 | + } else { |
363 | + $insert_vals .= ", 'N'"; |
364 | + $file_content .= "\npartial = N"; |
365 | + } |
366 | + |
367 | + # incremental (Y | N) |
368 | + if ($option_incremental) { |
369 | + $insert_vals .= ", 'Y'"; |
370 | + $file_content .= "\nincremental = Y"; |
371 | + } else { |
372 | + $insert_vals .= ", 'N'"; |
373 | + $file_content .= "\nincremental = N"; |
374 | + } |
375 | + |
376 | + # format (file | tar | xbsream) |
377 | + if ($option_stream eq 'tar') { |
378 | + $insert_vals .= ", 'tar'"; |
379 | + $file_content .= "\nformat = tar"; |
380 | + } elsif ($option_stream eq 'xbstream') { |
381 | + $insert_vals .= ", 'xbstream'"; |
382 | + $file_content .= "\nformat = xbstream"; |
383 | + } else { |
384 | + $insert_vals .= ", 'file'"; |
385 | + $file_content .= "\nformat = file"; |
386 | + } |
387 | + |
388 | + # compact (Y | N) |
389 | + if ($option_compact) { |
390 | + $insert_vals .= ", 'Y'"; |
391 | + $file_content .= "\ncompact = Y"; |
392 | + } else { |
393 | + $insert_vals .= ", 'N'"; |
394 | + $file_content .= "\ncompact = N"; |
395 | + } |
396 | + |
397 | + # compressed (Y | N) |
398 | + if ($option_compress) { |
399 | + $insert_vals .= ", 'Y'"; |
400 | + $file_content .= "\ncompressed = Y"; |
401 | + } else { |
402 | + $insert_vals .= ", 'N'"; |
403 | + $file_content .= "\ncompressed = N"; |
404 | + } |
405 | + |
406 | + # encrypted (Y | N) |
407 | + if ($option_encrypt) { |
408 | + $insert_vals .= ", 'Y'"; |
409 | + $file_content .= "\nencrypted = Y"; |
410 | + } else { |
411 | + $insert_vals .= ", 'N'"; |
412 | + $file_content .= "\nencrypted = N"; |
413 | + } |
414 | + |
415 | + # build and execute the query |
416 | + $insert_query = "INSERT INTO PERCONA_SCHEMA.xtrabackup_history(". |
417 | + "uuid, name, tool_name, tool_command, tool_version, ". |
418 | + "ibbackup_version, mysql_version, start_time, end_time, ". |
419 | + "lock_time, binlog_pos, innodb_from_lsn, innodb_to_lsn, ". |
420 | + "partial, incremental, format, compact, compressed, ". |
421 | + "encrypted) VALUES($insert_vals)"; |
422 | + |
423 | + mysql_query($con, $insert_query); |
424 | + |
425 | + print STDERR "$prefix Backup history record uuid $uuid successfully written\n"; |
426 | + |
427 | + # create the backup history file |
428 | + write_to_backup_file("$backup_history", "$file_content"); |
429 | +} |
430 | + |
431 | =pod |
432 | |
433 | =head1 NAME |
434 | @@ -3466,8 +3801,10 @@ |
435 | [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME] |
436 | [--databases=LIST] [--no-lock] |
437 | [--tmpdir=DIRECTORY] [--tables-file=FILE] |
438 | + [--no-history] [--history-name=NAME] |
439 | [--incremental] [--incremental-basedir] |
440 | [--incremental-dir] [--incremental-force-scan] [--incremental-lsn] |
441 | + [--incremental-history-name=NAME] [--incremental-history-uuid=UUID] |
442 | [--compact] |
443 | BACKUP-ROOT-DIR |
444 | |
445 | @@ -3637,6 +3974,14 @@ |
446 | |
447 | This option displays a help screen and exits. |
448 | |
449 | +=item --history-name |
450 | + |
451 | +This option specifies a backup name that will be placed within the history record. |
452 | + |
453 | +=item --no-history |
454 | + |
455 | +This option disables the creation of a backup history record and file. |
456 | + |
457 | =item --host=HOST |
458 | |
459 | This option specifies the host to use when connecting to the database server with TCP/IP. The option accepts a string argument. It is passed to the mysql child process without alteration. See mysql --help for details. |
460 | @@ -3661,6 +4006,14 @@ |
461 | |
462 | This option specifies the directory where the incremental backup will be combined with the full backup to make a new full backup. The option accepts a string argument. It is used with the --incremental option. |
463 | |
464 | +=item --incremental-history-name=NAME |
465 | + |
466 | +This option specifies the name of the backup series stored in the PERCONA_SCHEMA.xtrabackup_history history record to base an incremental backup on. Xtrabackup will search the history table looking for the most recent (highest innodb_to_lsn), successful backup in the series and take the to_lsn value to use as the starting lsn for the incremental backup. This will be mutually exclusive with --incremental-history-uuid, --incremental-basedir and --incremental-lsn. If no valid lsn can be found (no series by that name, no successful backups by that name) xtrabackup will return with an error. It is used with the --incremental option. |
467 | + |
468 | +=item --incremental-history-uuid=UUID |
469 | + |
470 | +This option specifies the UUID of the specific history record stored in the PERCONA_SCHEMA.xtrabackup_history to base an incremental backup on. --incremental-history-name, --incremental-basedir and --incremental-lsn. If no valid lsn can be found (no success record with that uuid) xtrabackup will return with an error. It is used with the --incremental option. |
471 | + |
472 | =item --incremental-force-scan |
473 | |
474 | This options tells xtrabackup to perform full scan of data files for taking an incremental backup even if full changed page bitmap data is available to enable the backup without the full scan. |
475 | |
476 | === added file 'test/t/history_on_server.sh' |
477 | --- test/t/history_on_server.sh 1970-01-01 00:00:00 +0000 |
478 | +++ test/t/history_on_server.sh 2013-09-10 19:03:04 +0000 |
479 | @@ -0,0 +1,199 @@ |
480 | +############################################################################### |
481 | +# Test history-on-server feature |
482 | +############################################################################### |
483 | + |
484 | +. inc/common.sh |
485 | + |
486 | + |
487 | +############################################################################### |
488 | +# Gets a single column value from the last history record added |
489 | +function get_one_value() |
490 | +{ |
491 | + local column=$1 |
492 | + shift |
493 | + val=`${MYSQL} ${MYSQL_ARGS} -Ns -e "SELECT $column FROM PERCONA_SCHEMA.xtrabackup_history ORDER BY start_time DESC LIMIT 1"` |
494 | +} |
495 | + |
496 | +############################################################################### |
497 | +# Checks a single column from the last history record added for some value and |
498 | +# not NULL. |
499 | +function check_for_not_NULL() |
500 | +{ |
501 | + local column=$1 |
502 | + shift |
503 | + get_one_value "$column" |
504 | + if [ -z "$val" ] || [ "$val" = "NULL" ]; |
505 | + then |
506 | + vlog "Error: $column in history record invalid, expected NULL" |
507 | + exit 1 |
508 | + fi |
509 | +} |
510 | + |
511 | + |
512 | +############################################################################### |
513 | +# Checks a single column from the last history record added to see if is a |
514 | +# specific value. |
515 | +function check_for_value() |
516 | +{ |
517 | + local column=$1 |
518 | + shift |
519 | + get_one_value "$column" |
520 | + if [ -z "$val" ] || [ "$val" != "$@" ]; |
521 | + then |
522 | + vlog "Error: $column in history record invalid, expected $@" |
523 | + exit 1 |
524 | + fi |
525 | +} |
526 | + |
527 | + |
528 | +############################################################################### |
529 | +vlog "Prepping server" |
530 | +start_server |
531 | +load_dbase_schema incremental_sample |
532 | +multi_row_insert incremental_sample.test \({1..100},100\) |
533 | +backup_dir=$topdir/backups |
534 | +mkdir $backup_dir |
535 | + |
536 | + |
537 | +############################################################################### |
538 | +# This tests the to make sure that no xtrabackup_history unless --history is |
539 | +# specified |
540 | +vlog "Testing no --history" |
541 | +innobackupex --stream=tar $backup_dir > /dev/null |
542 | + |
543 | +run_cmd_expect_failure get_one_value "uuid" |
544 | + |
545 | + |
546 | +############################################################################### |
547 | +# This tests the basic creation of a history record and that fields are |
548 | +# populated with some data. It also tests specifically that |
549 | +# partial, incremental, compact, compressed, encrypted and format are exactly |
550 | +# the correct values after the backup. |
551 | +# Missing is a test that binlog_pos is NULL, that would require restarting the |
552 | +# server without the log-bin option in the .cnf file but that has been tested |
553 | +# manually and doesn't seem to be something that would be required to be |
554 | +# validated. |
555 | +vlog "Testing basic history record" |
556 | +innobackupex --history=test1 --stream=tar $backup_dir > /dev/null |
557 | + |
558 | +for column in uuid name tool_name tool_command tool_version ibbackup_version \ |
559 | +mysql_version start_time end_time lock_time binlog_pos innodb_from_lsn \ |
560 | +innodb_to_lsn |
561 | +do |
562 | + check_for_not_NULL "$column" |
563 | +done |
564 | + |
565 | +for column in partial incremental compact compressed encrypted |
566 | +do |
567 | + check_for_value "$column" "N" |
568 | +done |
569 | + |
570 | +check_for_value "format" "tar" |
571 | + |
572 | +# saving for later |
573 | +get_one_value "innodb_to_lsn" |
574 | +first_to_lsn=$val |
575 | + |
576 | + |
577 | +############################################################################### |
578 | +# This tests the taking of an incremental backup based on the last record |
579 | +# of a history series and validates that the lsns in the record are correct. |
580 | +# It also tests that format, incremental and compact are exactly the correct |
581 | +# values after the backup. |
582 | +vlog "Testing incremental based on history name" |
583 | + |
584 | +multi_row_insert incremental_sample.test \({101..200},100\) |
585 | + |
586 | +innobackupex --history=test1 --incremental \ |
587 | +--incremental-history-name=test1 --compact $backup_dir > /dev/null |
588 | + |
589 | +# saving for later |
590 | +get_one_value "uuid" |
591 | +second_uuid=$val |
592 | +get_one_value "innodb_from_lsn" |
593 | +second_from_lsn=$val |
594 | +get_one_value "innodb_to_lsn" |
595 | +second_to_lsn=$val |
596 | + |
597 | +check_for_value "format" "file" |
598 | +check_for_value "incremental" "Y" |
599 | +check_for_value "compact" "Y" |
600 | + |
601 | +if [ -z "$second_from_lsn" ] || [ "$second_from_lsn" != "$first_to_lsn" ] |
602 | +then |
603 | + vlog "Second backup was not properly based on the to_lsn of the first" |
604 | + exit 1 |
605 | +fi |
606 | + |
607 | +multi_row_insert incremental_sample.test \({201..300},100\) |
608 | + |
609 | +# This will be a backup based on the last incremental just done, so, its |
610 | +# innodb_from_lsn (third_from_lsn) should be the same as the value in |
611 | +# second_to_lsn. This tests that we find the right record in the test1 series |
612 | +# out of the two records that should be present before the backup is done. |
613 | +innobackupex --history=test1 --incremental \ |
614 | +--incremental-history-name=test1 $backup_dir > /dev/null |
615 | + |
616 | +# saving for later |
617 | +get_one_value "uuid" |
618 | +third_uuid=$val |
619 | +get_one_value "innodb_from_lsn" |
620 | +third_from_lsn=$val |
621 | +get_one_value "innodb_to_lsn" |
622 | +third_to_lsn=$val |
623 | + |
624 | +if [ -z "$third_from_lsn" ] || [ "$third_from_lsn" != "$second_to_lsn" ] |
625 | +then |
626 | + vlog "Third backup was not properly based on the to_lsn of the second" |
627 | + exit 1 |
628 | +fi |
629 | + |
630 | + |
631 | +############################################################################### |
632 | +# This tests that we can base an incremental on a specific history record |
633 | +# identified by its uuid that we captured earlier from a history record or it |
634 | +# could be scraped from the output of innobackupex at some point in the past. |
635 | +# It also tests specifically that incremental, compressed, encrypted and format |
636 | +# are exactly the correct values after the backup. |
637 | +# It tests that --history can be specified, resulting in a history record with |
638 | +# no name |
639 | +vlog "Testing incremental based on history uuid" |
640 | +multi_row_insert incremental_sample.test \({301..400},100\) |
641 | + |
642 | +innobackupex --history --incremental --incremental-history-uuid=$third_uuid \ |
643 | +--stream=xbstream --compress --encrypt=AES256 \ |
644 | +--encrypt-key=percona_xtrabackup_is_awesome___ $backup_dir > /dev/null |
645 | + |
646 | +get_one_value "innodb_from_lsn" |
647 | +fourth_from_lsn=$val |
648 | + |
649 | +for column in incremental compressed encrypted |
650 | +do |
651 | + check_for_value "$column" "Y" |
652 | +done |
653 | + |
654 | +check_for_value "format" "xbstream" |
655 | +check_for_value "name" "NULL" |
656 | + |
657 | +if [ -z "$fourth_from_lsn" ] || [ "$fourth_from_lsn" != "$third_to_lsn" ] |
658 | +then |
659 | + vlog "Fourth backup was not properly based on the to_lsn of the third" |
660 | + exit 1 |
661 | +fi |
662 | + |
663 | + |
664 | +############################################################################### |
665 | +# This tests that innobackupex fails when an invalid --incremental-history-name |
666 | +# is given. |
667 | +vlog "Testing bad --incremental-history-name" |
668 | +run_cmd_expect_failure $IB_BIN $IB_ARGS --incremental \ |
669 | +--incremental-history-name=foo --stream=tar $backup_dir > /dev/null |
670 | + |
671 | + |
672 | + |
673 | +############################################################################### |
674 | +# This tests that innobackupex fails when an invalid --incremental-history-uuid |
675 | +# is given. |
676 | +vlog "Testing bad --incremental-history-uuid" |
677 | +run_cmd_expect_failure $IB_BIN $IB_ARGS --incremental \ |
678 | +--incremental-history-uuid=foo --stream=tar $backup_dir > /dev/null |
George, this should go to 2.2 only. I will update blueprints and branches.