summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-03-26 13:51:15 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-03-26 13:51:15 +0200
commit065ba53ccbf3ab468408dc5a5dbcb3741750a02d (patch)
tree05f3973d2d4dde2db4d711fb3414c566881b106a
parent6fbbb0853e7e58621f73f0afc600cd95995413ed (diff)
downloadmariadb-git-065ba53ccbf3ab468408dc5a5dbcb3741750a02d.tar.gz
MDEV-12711 mariabackup --backup is refused for multi-file system tablespace
Before MDEV-12113 (MariaDB Server 10.1.25), on shutdown InnoDB would write the current LSN to the first page of each file of the system tablespace. This is incompatible with MariaDB's InnoDB table encryption, because encryption repurposed the field for an encryption key ID and checksum. buf_page_is_corrupted(): For the InnoDB system tablespace, skip FIL_PAGE_FILE_FLUSH_LSN when checking if a page is all zero, because the first page of each file in the system tablespace can contain nonzero bytes in the field.
-rw-r--r--mysql-test/suite/mariabackup/absolute_ibdata_paths.opt2
-rw-r--r--mysql-test/suite/mariabackup/absolute_ibdata_paths.test26
-rw-r--r--storage/innobase/buf/buf0buf.cc33
-rw-r--r--storage/xtradb/buf/buf0buf.cc31
4 files changed, 68 insertions, 24 deletions
diff --git a/mysql-test/suite/mariabackup/absolute_ibdata_paths.opt b/mysql-test/suite/mariabackup/absolute_ibdata_paths.opt
index 52b6b743ac8..28848b9b086 100644
--- a/mysql-test/suite/mariabackup/absolute_ibdata_paths.opt
+++ b/mysql-test/suite/mariabackup/absolute_ibdata_paths.opt
@@ -1 +1 @@
---innodb --innodb-data-home-dir= --innodb-data-file-path=$MYSQLTEST_VARDIR/tmp/absolute_path_ibdata1:3M;ibdata_second:1M:autoextend \ No newline at end of file
+--innodb --innodb-data-home-dir= --innodb-data-file-path=$MYSQLTEST_VARDIR/tmp/absolute_path_ibdata1:6M;ibdata_second:1M:autoextend
diff --git a/mysql-test/suite/mariabackup/absolute_ibdata_paths.test b/mysql-test/suite/mariabackup/absolute_ibdata_paths.test
index 6717f16d199..fa304f0bc55 100644
--- a/mysql-test/suite/mariabackup/absolute_ibdata_paths.test
+++ b/mysql-test/suite/mariabackup/absolute_ibdata_paths.test
@@ -2,12 +2,32 @@
# Innodb system tablespace is specified with absolute path in the .opt file
CREATE TABLE t(i INT) ENGINE INNODB;
INSERT INTO t VALUES(1);
+
+let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
+let MYSQLD_DATADIR= `SELECT @@datadir`;
+--source include/shutdown_mysqld.inc
+perl;
+my $file= "$ENV{MYSQLD_DATADIR}/ibdata_second";
+open(FILE, "+<", $file) or die "Unable to open $file\n";
+binmode FILE;
+my $ps= $ENV{INNODB_PAGE_SIZE};
+my $page;
+my $pos = $ps * 0;
+sysseek(FILE, $pos, 0) || die "Unable to seek $file\n";
+die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
+substr($page,26,8) = pack("NN", 1, 1);
+sysseek(FILE, $pos, 0) || die "Unable to rewind $file\n";
+syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
+close(FILE) || die "Unable to close $file\n";
+EOF
+
+--source include/start_mysqld.inc
+
echo # xtrabackup backup;
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
let $_innodb_data_file_path=`select @@innodb_data_file_path`;
let $_innodb_data_home_dir=`select @@innodb_data_home_dir`;
-let $_datadir= `SELECT @@datadir`;
--disable_result_log
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
@@ -16,11 +36,11 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir;
--source include/shutdown_mysqld.inc
echo # remove datadir;
-rmdir $_datadir;
+rmdir $MYSQLD_DATADIR;
#remove out-of-datadir ibdata1
remove_file $MYSQLTEST_VARDIR/tmp/absolute_path_ibdata1;
echo # xtrabackup copy back;
-exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir "--innodb_data_file_path=$_innodb_data_file_path" --innodb_data_home_dir=$_innodb_data_home_dir;
+exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$MYSQLD_DATADIR --target-dir=$targetdir "--innodb_data_file_path=$_innodb_data_file_path" --innodb_data_home_dir=$_innodb_data_home_dir;
echo # restart server;
--source include/start_mysqld.inc
--enable_result_log
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 621433c1c5c..78200198e62 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -946,18 +946,31 @@ buf_page_is_corrupted(
#error "FIL_PAGE_LSN must be 64 bit aligned"
#endif
- /* declare empty pages non-corrupted */
- if (checksum_field1 == 0 && checksum_field2 == 0
- && *reinterpret_cast<const ib_uint64_t*>(read_buf +
- FIL_PAGE_LSN) == 0) {
- /* make sure that the page is really empty */
- for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) {
- if (read_buf[i] != 0) {
- return(true);
+ /* A page filled with NUL bytes is considered not corrupted.
+ The FIL_PAGE_FILE_FLUSH_LSN field may be written nonzero for
+ the first page of each file of the system tablespace.
+ Ignore it for the system tablespace. */
+ if (!checksum_field1 && !checksum_field2) {
+ ulint i = 0;
+ do {
+ if (read_buf[i]) {
+ return true;
}
- }
+ } while (++i < FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
- return(false);
+#ifndef UNIV_INNOCHECKSUM
+ if (!space || !space->id) {
+ /* Skip FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ in the system tablespace. */
+ i += 8;
+ }
+#endif
+ do {
+ if (read_buf[i]) {
+ return true;
+ }
+ } while (++i < srv_page_size);
+ return false;
}
switch (curr_algo) {
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index f4ef3ca7015..773b528b40d 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -945,18 +945,29 @@ buf_page_is_corrupted(
#error "FIL_PAGE_LSN must be 64 bit aligned"
#endif
- /* declare empty pages non-corrupted */
- if (checksum_field1 == 0 && checksum_field2 == 0
- && *reinterpret_cast<const ib_uint64_t*>(read_buf +
- FIL_PAGE_LSN) == 0) {
- /* make sure that the page is really empty */
- for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) {
- if (read_buf[i] != 0) {
- return(true);
+ /* A page filled with NUL bytes is considered not corrupted.
+ The FIL_PAGE_FILE_FLUSH_LSN field may be written nonzero for
+ the first page of each file of the system tablespace.
+ Ignore it for the system tablespace. */
+ if (!checksum_field1 && !checksum_field2) {
+ ulint i = 0;
+ do {
+ if (read_buf[i]) {
+ return true;
}
- }
+ } while (++i < FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
- return(false);
+ if (!space || !space->id) {
+ /* Skip FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ in the system tablespace. */
+ i += 8;
+ }
+ do {
+ if (read_buf[i]) {
+ return true;
+ }
+ } while (++i < srv_page_size);
+ return false;
}
switch (curr_algo) {