Commit cad56fba authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-18733 MariaDB slow start after crash recovery

If InnoDB crash recovery was needed, the InnoDB function srv_start()
would invoke extra validation, reading something from every InnoDB
data file. This should be unnecessary now that MDEV-14717 made
RENAME operations crash-safe inside InnoDB (which can be
disabled in MariaDB 10.2 by setting innodb_safe_truncate=OFF).

dict_check_sys_tables(): Skip tables that would be dropped by
row_mysql_drop_garbage_tables(). Perform extra validation only
if innodb_safe_truncate=OFF, innodb_force_recovery=0 and
crash recovery was needed.

dict_load_table_one(): Validate the root page of the table.
In this way, we can deny access to corrupted or mismatching tables
not only after crash recovery, but also after a clean shutdown.
parent 7984ea80
......@@ -3,6 +3,7 @@ call mtr.add_suppression("Plugin 'file_key_management' registration.*failed");
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[12]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted");
call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found");
# Start server with keys2.txt
SET GLOBAL innodb_file_per_table = ON;
......@@ -27,7 +28,7 @@ foobar 2
# Restart server with keysbad3.txt
SELECT * FROM t1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
DROP TABLE t1;
# Start server with keys3.txt
SET GLOBAL innodb_default_encryption_key_id=5;
......@@ -36,33 +37,31 @@ INSERT INTO t2 VALUES ('foobar',1,2);
# Restart server with keys2.txt
SELECT * FROM t2;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
SELECT * FROM t2 where id = 1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
SELECT * FROM t2 where b = 1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
INSERT INTO t2 VALUES ('tmp',3,3);
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
DELETE FROM t2 where b = 3;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
DELETE FROM t2 where id = 3;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
UPDATE t2 set b = b +1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
OPTIMIZE TABLE t2;
Table Op Msg_type Msg_text
test.t2 optimize Warning Table t2 in file ./test/t2.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t2 optimize Error Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
test.t2 optimize error Corrupt
test.t2 optimize Error Table 'test.t2' doesn't exist in engine
test.t2 optimize status Operation failed
ALTER TABLE t2 ADD COLUMN d INT;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
test.t2 analyze Warning Table t2 in file ./test/t2.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t2 analyze Error Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
test.t2 analyze error Corrupt
test.t2 analyze Error Table 'test.t2' doesn't exist in engine
test.t2 analyze status Operation failed
TRUNCATE TABLE t2;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
DROP TABLE t2;
# Start server with keys2.txt
......@@ -2,48 +2,42 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page n
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
call mtr.add_suppression("InnoDB: Tablespace for table \`test\`.\`t1\` is set as discarded\\.");
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
SET GLOBAL innodb_file_per_table = ON;
CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB
ENCRYPTED=YES ENCRYPTION_KEY_ID=4;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
SELECT * FROM t1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
SHOW WARNINGS;
Level Code Message
Warning 192 Table test/t1 in tablespace is encrypted but encryption service or used key_id is not available. Can't continue reading table.
Warning 192 Table t1 in file ./test/t1.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
Error 1296 Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
Error 1932 Table 'test.t1' doesn't exist in engine
ALTER TABLE t1 ENGINE=InnoDB;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
SHOW WARNINGS;
Level Code Message
Warning 192 Table t1 in file ./test/t1.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
Error 1296 Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
Error 1932 Table 'test.t1' doesn't exist in engine
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize Warning Table t1 in file ./test/t1.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t1 optimize Error Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
test.t1 optimize error Corrupt
test.t1 optimize Error Table 'test.t1' doesn't exist in engine
test.t1 optimize status Operation failed
SHOW WARNINGS;
Level Code Message
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check Warning Table t1 in file ./test/t1.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t1 check Error Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
test.t1 check error Corrupt
test.t1 check Error Table 'test.t1' doesn't exist in engine
test.t1 check status Operation failed
SHOW WARNINGS;
Level Code Message
FLUSH TABLES t1 FOR EXPORT;
backup: t1
UNLOCK TABLES;
ALTER TABLE t1 DISCARD TABLESPACE;
Warnings:
Warning 192 Table test/t1 in tablespace is encrypted but encryption service or used key_id is not available. Can't continue reading table.
Warning 1812 Tablespace is missing for table 'test/t1'
ERROR 42S02: Table 'test.t1' doesn't exist in engine
restore: t1 .ibd and .cfg files
ALTER TABLE t1 DISCARD TABLESPACE;
restore: t1 .ibd and .cfg files
ALTER TABLE t1 IMPORT TABLESPACE;
Warnings:
Warning 1814 Tablespace has been discarded for table `t1`
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
......@@ -52,6 +46,7 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`pk`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=4
RENAME TABLE t1 TO t1new;
ALTER TABLE t1new RENAME TO t2new;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
DROP TABLE t1new;
ERROR HY000: Error on rename of './test/t1' to './test/t1new' (errno: 155 "The table does not exist in the storage engine")
ALTER TABLE t1 RENAME TO t1new;
ERROR 42S02: Table 'test.t1' doesn't exist in engine
DROP TABLE t1;
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
SET GLOBAL innodb_file_per_table = ON;
CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB
ENCRYPTED=YES ENCRYPTION_KEY_ID=4;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize Warning Table test/t1 in tablespace is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t1 optimize Warning Table t1 in file ./test/t1.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t1 optimize Error Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
test.t1 optimize error Corrupt
test.t1 optimize Error Table 'test.t1' doesn't exist in engine
test.t1 optimize status Operation failed
SHOW WARNINGS;
Level Code Message
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check Warning Table t1 in file ./test/t1.ibd is encrypted but encryption service or used key_id is not available. Can't continue reading table.
test.t1 check Error Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
test.t1 check error Corrupt
test.t1 check Error Table 'test.t1' doesn't exist in engine
test.t1 check status Operation failed
SHOW WARNINGS;
Level Code Message
DROP TABLE t1;
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Unable to decompress ..test.t[1-3]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted");
# Restart mysqld --file-key-management-filename=keys2.txt
SET GLOBAL innodb_file_per_table = ON;
set GLOBAL innodb_default_encryption_key_id=4;
......@@ -14,9 +15,9 @@ insert into t2 values (1, repeat('secret',6000));
insert into t3 values (1, repeat('secret',6000));
# Restart mysqld --file-key-management-filename=keys3.txt
select count(*) from t1 FORCE INDEX (b) where b like 'secret%';
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
select count(*) from t2 FORCE INDEX (b) where b like 'secret%';
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t2' doesn't exist in engine
select count(*) from t3 FORCE INDEX (b) where b like 'secret%';
count(*)
1
......
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[15]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t[15].ibd looks corrupted; key_version=1");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[15]` is corrupted");
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
create table t5 (
`intcol1` int(32) DEFAULT NULL,
......@@ -20,8 +21,8 @@ CREATE TABLE `t1` (
insert into t1 values (1,2,'maria','db','encryption');
alter table t1 encrypted='yes' `encryption_key_id`=1;
select * from t1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
select * from t5;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t5' doesn't exist in engine
drop table t1;
drop table t5;
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=\\d+, page number=[36]\\] in file .*test.t[123]\\.ibd looks corrupted; key_version=3221342974");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[13]` is corrupted");
SET GLOBAL innodb_file_per_table = ON;
set global innodb_compression_algorithm = 1;
# Create and populate tables to be corrupted
......@@ -14,10 +15,10 @@ COMMIT;
# Backup tables before corrupting
# Corrupt tables
SELECT * FROM t1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
SELECT * FROM t2;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
SELECT * FROM t3;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t3' doesn't exist in engine
# Restore the original tables
DROP TABLE t1,t2,t3;
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file .*test.t[12].ibd looks corrupted; key_version=1");
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
# Start server with keys2.txt
CREATE TABLE t1(a int not null primary key auto_increment, b varchar(128)) engine=innodb ENCRYPTED=YES ENCRYPTION_KEY_ID=19;
CREATE TABLE t2(a int not null primary key auto_increment, b varchar(128)) engine=innodb ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
......@@ -34,11 +35,11 @@ SELECT COUNT(1) FROM t2;
COUNT(1)
2048
SELECT COUNT(1) FROM t2,t1 where t2.a = t1.a;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
SELECT COUNT(1) FROM t1 where b = 'ab';
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
SELECT COUNT(1) FROM t1;
ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB
ERROR 42S02: Table 'test.t1' doesn't exist in engine
# Start server with keys2.txt
SELECT COUNT(1) FROM t1;
......
......@@ -13,6 +13,7 @@ call mtr.add_suppression("Plugin 'file_key_management' registration.*failed");
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[12]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted");
call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found");
--echo # Start server with keys2.txt
......@@ -39,7 +40,7 @@ SELECT * FROM t1;
-- source include/restart_mysqld.inc
--disable_warnings
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t1;
--enable_warnings
......@@ -70,36 +71,35 @@ INSERT INTO t2 VALUES ('foobar',1,2);
-- source include/restart_mysqld.inc
--disable_warnings
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t2;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t2 where id = 1;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t2 where b = 1;
--replace_regex /tablespace [0-9]*/tablespace /
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
INSERT INTO t2 VALUES ('tmp',3,3);
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
DELETE FROM t2 where b = 3;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
DELETE FROM t2 where id = 3;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
UPDATE t2 set b = b +1;
OPTIMIZE TABLE t2;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
ALTER TABLE t2 ADD COLUMN d INT;
ANALYZE TABLE t2;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
TRUNCATE TABLE t2;
DROP TABLE t2;
......
......@@ -13,6 +13,7 @@ call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]
# Suppression for builds where file_key_management plugin is linked statically
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
call mtr.add_suppression("InnoDB: Tablespace for table \`test\`.\`t1\` is set as discarded\\.");
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
--let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
--source include/restart_mysqld.inc
......@@ -26,11 +27,11 @@ INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
--let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt
--source include/restart_mysqld.inc
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t1;
--replace_regex /(tablespace|key_id) [1-9][0-9]*/\1 /
SHOW WARNINGS;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
ALTER TABLE t1 ENGINE=InnoDB;
--replace_regex /(tablespace|key_id) [1-9][0-9]*/\1 /
SHOW WARNINGS;
......@@ -57,8 +58,7 @@ UNLOCK TABLES;
--let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt
--source include/restart_mysqld.inc
# Discard should pass even with incorrect keys
--replace_regex /(tablespace|key_id) [1-9][0-9]*/\1 /
--error ER_NO_SUCH_TABLE_IN_ENGINE
ALTER TABLE t1 DISCARD TABLESPACE;
perl;
......@@ -71,19 +71,23 @@ EOF
--let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
--source include/restart_mysqld.inc
ALTER TABLE t1 DISCARD TABLESPACE;
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_discard_tablespaces("test", "t1");
ib_restore_tablespaces("test", "t1");
EOF
ALTER TABLE t1 IMPORT TABLESPACE;
SHOW CREATE TABLE t1;
--let $restart_parameters= --innodb-encrypt-tables --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt
--source include/restart_mysqld.inc
# Rename table should pass even with incorrect keys
--error ER_ERROR_ON_RENAME
RENAME TABLE t1 TO t1new;
--replace_regex /(tablespace|key_id) [1-9][0-9]*/\1 /
# Alter table rename is not allowed with incorrect keys
--error ER_GET_ERRMSG
ALTER TABLE t1new RENAME TO t2new;
--error ER_NO_SUCH_TABLE_IN_ENGINE
ALTER TABLE t1 RENAME TO t1new;
# Drop should pass even with incorrect keys
--replace_regex /(tablespace|key_id) [1-9][0-9]*/\1 /
DROP TABLE t1new;
DROP TABLE t1;
......@@ -11,6 +11,7 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page n
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
# Suppression for builds where file_key_management plugin is linked statically
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
--let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
--source include/restart_mysqld.inc
......
......@@ -7,6 +7,7 @@
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Unable to decompress ..test.t[1-3]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted");
--echo # Restart mysqld --file-key-management-filename=keys2.txt
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
......@@ -27,9 +28,9 @@ insert into t3 values (1, repeat('secret',6000));
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt
-- source include/restart_mysqld.inc
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
select count(*) from t1 FORCE INDEX (b) where b like 'secret%';
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
select count(*) from t2 FORCE INDEX (b) where b like 'secret%';
select count(*) from t3 FORCE INDEX (b) where b like 'secret%';
......
......@@ -10,6 +10,7 @@
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[15]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t[15].ibd looks corrupted; key_version=1");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[15]` is corrupted");
# Suppression for builds where file_key_management plugin is linked statically
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
......@@ -41,9 +42,9 @@ alter table t1 encrypted='yes' `encryption_key_id`=1;
--let $restart_parameters=--innodb-encrypt-tables=OFF
--source include/restart_mysqld.inc
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
select * from t1;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
select * from t5;
--let $restart_parameters=--innodb-encrypt-tables=ON --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
......
......@@ -8,6 +8,7 @@
-- source include/not_embedded.inc
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=\\d+, page number=[36]\\] in file .*test.t[123]\\.ibd looks corrupted; key_version=3221342974");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[13]` is corrupted");
SET GLOBAL innodb_file_per_table = ON;
set global innodb_compression_algorithm = 1;
......@@ -65,11 +66,11 @@ EOF
--source include/start_mysqld.inc
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t1;
--error ER_GET_ERRMSG
SELECT * FROM t2;
--error ER_GET_ERRMSG
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t3;
--source include/shutdown_mysqld.inc
......
......@@ -10,6 +10,7 @@
call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted\\.");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file .*test.t[12].ibd looks corrupted; key_version=1");
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
--echo # Start server with keys2.txt
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
......@@ -44,11 +45,11 @@ CREATE TABLE t4(a int not null primary key auto_increment, b varchar(128)) engin
SELECT SLEEP(5);
SELECT COUNT(1) FROM t3;
SELECT COUNT(1) FROM t2;
--error 1296
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT COUNT(1) FROM t2,t1 where t2.a = t1.a;
--error 1296
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT COUNT(1) FROM t1 where b = 'ab';
--error 1296
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT COUNT(1) FROM t1;
--echo
......
......@@ -10,39 +10,19 @@ connection default;
# Cleanly shutdown mysqld
disconnect con1;
# Corrupt FIL_PAGE_OFFSET in bug16720368.ibd,
# and update the checksum to the "don't care" value.
# and recompute innodb_checksum_algorithm=crc32
# Restart mysqld
# This will succeed after a clean shutdown, due to
# fil_open_single_table_tablespace(check_space_id=FALSE).
SELECT COUNT(*) FROM bug16720368;
COUNT(*)
8
INSERT INTO bug16720368_1 VALUES(1);
# The table is unaccessible, because after a crash we will
# validate the tablespace header.
SELECT COUNT(*) FROM bug16720368;
ERROR 42S02: Table 'test.bug16720368' doesn't exist in engine
INSERT INTO bug16720368 VALUES(0,1);
INSERT INTO bug16720368 VALUES(1);
ERROR 42S02: Table 'test.bug16720368' doesn't exist in engine
# The table is readable thanks to innodb-force-recovery.
SELECT COUNT(*) FROM bug16720368;
COUNT(*)
8
INSERT INTO bug16720368 VALUES(0,1);
# Shut down the server cleanly to hide the corruption.
# The table is accessible, because after a clean shutdown we will
# NOT validate the tablespace header.
# We can modify the existing pages, but we cannot allocate or free
# any pages, because that would hit the corruption on page 0.
SELECT COUNT(*) FROM bug16720368;
COUNT(*)
9
INSERT INTO bug16720368_1 VALUES(1);
# Shut down the server to uncorrupt the data.
# Restart the server after uncorrupting the file.
INSERT INTO bug16720368 VALUES(9,1);
SELECT COUNT(*) FROM bug16720368;
COUNT(*)
10
9
DROP TABLE bug16720368, bug16720368_1;
#
# Bug#16735660 ASSERT TABLE2 == NULL, ROLLBACK OF RESURRECTED TXNS,
......
......@@ -18,6 +18,7 @@ call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore this and
call mtr.add_suppression("InnoDB: Plugin initialization aborted*");
call mtr.add_suppression("Plugin 'InnoDB' init function returned error.");
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed.");
call mtr.add_suppression("InnoDB: Table `test`\\.`bug16720368` is corrupted");
-- enable_query_log
-- echo #
......@@ -40,67 +41,62 @@ connection default;
disconnect con1;
-- echo # Corrupt FIL_PAGE_OFFSET in bug16720368.ibd,
-- echo # and update the checksum to the "don't care" value.
-- echo # and recompute innodb_checksum_algorithm=crc32
perl;
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
my $file = "$ENV{MYSQLD_DATADIR}/test/bug16720368.ibd";
open(FILE, "+<$file") || die "Unable to open $file";
print FILE pack("H*","deadbeefc001cafe") || die "Unable to write $file";
seek(FILE, $ENV{PAGE_SIZE}-8, 0) || die "Unable to seek $file";
print FILE pack("H*","deadbeef") || die "Unable to write $file";
binmode FILE;
my $ps= $ENV{PAGE_SIZE};
my $page;
sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
substr($page,4,4)=pack("N",0xc001cafe);
my $polynomial = 0x82f63b78; # CRC-32C
my $ck= pack("N",mycrc32(substr($page, 4, 22), 0, $polynomial) ^
mycrc32(substr($page, 38, $ps - 38 - 8), 0, $polynomial));
substr($page,0,4)=$ck;
substr($page,$ps-8,4)=$ck;
sysseek(FILE, 3*$ps, 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";
EOF
-- echo # Restart mysqld
-- source include/start_mysqld.inc
-- echo # This will succeed after a clean shutdown, due to
-- echo # fil_open_single_table_tablespace(check_space_id=FALSE).
SELECT COUNT(*) FROM bug16720368;
INSERT INTO bug16720368_1 VALUES(1);
--let $shutdown_timeout= 0
--source include/restart_mysqld.inc
-- echo # The table is unaccessible, because after a crash we will
-- echo # validate the tablespace header.
--error ER_NO_SUCH_TABLE_IN_ENGINE
SELECT COUNT(*) FROM bug16720368;
--error ER_NO_SUCH_TABLE_IN_ENGINE
INSERT INTO bug16720368 VALUES(0,1);
let $restart_parameters = --innodb-force-recovery=3;
--let $shutdown_timeout= 0
--source include/restart_mysqld.inc
-- echo # The table is readable thanks to innodb-force-recovery.
SELECT COUNT(*) FROM bug16720368;
INSERT INTO bug16720368 VALUES(0,1);
-- echo # Shut down the server cleanly to hide the corruption.
let $shutdown_timeout=;
let $restart_parameters =;
-- source include/restart_mysqld.inc
-- echo # The table is accessible, because after a clean shutdown we will
-- echo # NOT validate the tablespace header.
-- echo # We can modify the existing pages, but we cannot allocate or free
-- echo # any pages, because that would hit the corruption on page 0.
SELECT COUNT(*) FROM bug16720368;
INSERT INTO bug16720368 VALUES(1);
INSERT INTO bug16720368_1 VALUES(1);
-- echo # Shut down the server to uncorrupt the data.
-- source include/shutdown_mysqld.inc
# Uncorrupt the FIL_PAGE_OFFSET.
perl;
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
my $file = "$ENV{MYSQLD_DATADIR}/test/bug16720368.ibd";
open(FILE, "+<$file") || die "Unable to open $file";
# Uncorrupt FIL_PAGE_OFFSET.
print FILE pack("H*","deadbeef00000000") || die "Unable to write $file";
binmode FILE;
my $ps= $ENV{PAGE_SIZE};
my $page;
sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
substr($page,4,4)=pack("N",3);
my $polynomial = 0x82f63b78; # CRC-32C
my $ck= pack("N",mycrc32(substr($page, 4, 22), 0, $polynomial) ^
mycrc32(substr($page, 38, $ps - 38 - 8), 0, $polynomial));
substr($page,0,4)=$ck;
substr($page,$ps-8,4)=$ck;
sysseek(FILE, 3*$ps, 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";
EOF
-- echo # Restart the server after uncorrupting the file.
-- source include/start_mysqld.inc
INSERT INTO bug16720368 VALUES(9,1);
......
......@@ -4622,7 +4622,9 @@ buf_page_get_gen(
buf_pool_mutex_exit(buf_pool);
rw_lock_x_unlock(&fix_block->lock);
if (err) {
*err = DB_PAGE_CORRUPTED;
}
return NULL;
}
}
......
......@@ -1360,14 +1360,9 @@ dict_sys_tables_rec_read(
/** Load and check each non-predefined tablespace mentioned in SYS_TABLES.
Search SYS_TABLES and check each tablespace mentioned that has not
already been added to the fil_system. If it is valid, add it to the
file_system list. Perform extra validation on the table if recovery from
the REDO log occurred.
@param[in] validate Whether to do validation on the table.
file_system list.
@return the highest space ID found. */
UNIV_INLINE
ulint
dict_check_sys_tables(
bool validate)
static ulint dict_check_sys_tables()
{
ulint max_space_id = 0;
btr_pcur_t pcur;
......@@ -1390,6 +1385,10 @@ dict_check_sys_tables(
sys_datafiles = dict_table_get_low("SYS_DATAFILES");
ut_a(sys_datafiles != NULL);
const bool validate = recv_needed_recovery
&& !srv_safe_truncate
&& !srv_force_recovery;
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
rec != NULL;
rec = dict_getnext_system(&pcur, &mtr)) {
......@@ -1420,15 +1419,23 @@ dict_check_sys_tables(
&table_id, &space_id,
&n_cols, &flags, &flags2)
|| space_id == TRX_SYS_SPACE) {
next:
ut_free(table_name.m_name);
continue;
}
if (srv_safe_truncate
&& strstr(table_name.m_name, "/" TEMP_FILE_PREFIX "-")) {
/* This table will be dropped by
row_mysql_drop_garbage_tables().
We do not care if the file exists. */
goto next;
}
if (flags2 & DICT_TF2_DISCARDED) {
ib::info() << "Ignoring tablespace for " << table_name
<< " because the DISCARD flag is set .";
ut_free(table_name.m_name);
continue;
goto next;
}
/* For tables or partitions using .ibd files, the flag
......@@ -1503,11 +1510,8 @@ space_id information in the data dictionary to what we find in the
tablespace file. In addition, more validation will be done if recovery
was needed and force_recovery is not set.
We also scan the biggest space id, and store it to fil_system.
@param[in] validate true if recovery was needed */
void
dict_check_tablespaces_and_store_max_id(
bool validate)
We also scan the biggest space id, and store it to fil_system. */
void dict_check_tablespaces_and_store_max_id()
{
mtr_t mtr;
......@@ -1528,7 +1532,7 @@ dict_check_tablespaces_and_store_max_id(
/* Open all tablespaces referenced in SYS_TABLES.
This will update SYS_TABLESPACES and SYS_DATAFILES if it
finds any file-per-table tablespaces not already there. */
max_space_id = dict_check_sys_tables(validate);
max_space_id = dict_check_sys_tables();
fil_set_max_space_id_if_bigger(max_space_id);
mutex_exit(&dict_sys->mutex);
......@@ -3063,8 +3067,31 @@ dict_load_table_one(
if (table->space
&& !fil_space_get_size(table->space)) {
corrupted:
table->corrupted = true;
table->file_unreadable = true;
} else {
const page_id_t page_id(
table->space,
dict_table_get_first_index(table)
->page);
mtr.start();
buf_block_t* block = buf_page_get(
page_id,
dict_table_page_size(table),
RW_S_LATCH, &mtr);
const bool corrupted = !block
|| page_get_space_id(block->frame)
!= page_id.space()
|| page_get_page_no(block->frame)
!= page_id.page_no()
|| mach_read_from_2(FIL_PAGE_TYPE
+ block->frame)
!= FIL_PAGE_INDEX;
mtr.commit();
if (corrupted) {
goto corrupted;
}
}
}
} else {
......
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -76,11 +76,8 @@ space_id information in the data dictionary to what we find in the
tablespace file. In addition, more validation will be done if recovery
was needed and force_recovery is not set.
We also scan the biggest space id, and store it to fil_system.
@param[in] validate true if recovery was needed */
void
dict_check_tablespaces_and_store_max_id(
bool validate);
We also scan the biggest space id, and store it to fil_system. */
void dict_check_tablespaces_and_store_max_id();
/********************************************************************//**
Finds the first table name in the given database.
......
......@@ -2486,19 +2486,8 @@ innobase_start_or_create_for_mysql()
every table in the InnoDB data dictionary that has
an .ibd file.
We also determine the maximum tablespace id used.
The 'validate' flag indicates that when a tablespace
is opened, we also read the header page and validate
the contents to the data dictionary. This is time
consuming, especially for databases with lots of ibd
files. So only do it after a crash and not forcing
recovery. Open rw transactions at this point is not
a good reason to validate. */
bool validate = recv_needed_recovery
&& srv_force_recovery == 0;
dict_check_tablespaces_and_store_max_id(validate);
We also determine the maximum tablespace id used. */
dict_check_tablespaces_and_store_max_id();
}
/* Fix-up truncate of table if server crashed while truncate
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment