Problem:
======== During ibd file creation, InnoDB flushes the page0 without crypt information. During recovery, InnoDB encounters encrypted page read before initialising the crypt data of the tablespace. So it leads t corruption of page and doesn't allow innodb to start. Solution: ========= Write crypt_data information in page0 while creating .ibd file creation. During recovery, crypt_data will be initialised while processing MLOG_FILE_NAME redo log record.
This commit is contained in:
parent
fe6eac0cf7
commit
dc91372de3
26
mysql-test/suite/encryption/r/file_creation.result
Normal file
26
mysql-test/suite/encryption/r/file_creation.result
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
SET GLOBAL innodb_encrypt_tables = ON;
|
||||||
|
SET GLOBAL innodb_encryption_threads = 1;
|
||||||
|
SET GLOBAL innodb_max_dirty_pages_pct = 99;
|
||||||
|
SHOW VARIABLES LIKE 'innodb_encrypt%';
|
||||||
|
Variable_name Value
|
||||||
|
innodb_encrypt_log OFF
|
||||||
|
innodb_encrypt_tables ON
|
||||||
|
innodb_encrypt_temporary_tables OFF
|
||||||
|
innodb_encryption_rotate_key_age 1
|
||||||
|
innodb_encryption_rotation_iops 100
|
||||||
|
innodb_encryption_threads 1
|
||||||
|
CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(255), f3 CHAR(255),
|
||||||
|
f4 CHAR(255), f5 CHAR(255))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1, "mysql", "mariadb", "batman", "superman");
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
# Wait max 10 min for key encryption threads to encrypt all spaces
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
|
||||||
|
test.t1 optimize status OK
|
||||||
|
ALTER TABLE t1 FORCE;
|
||||||
|
# Kill the server
|
||||||
|
DROP TABLE t1;
|
1
mysql-test/suite/encryption/t/file_creation.opt
Normal file
1
mysql-test/suite/encryption/t/file_creation.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--innodb-tablespaces-encryption
|
41
mysql-test/suite/encryption/t/file_creation.test
Normal file
41
mysql-test/suite/encryption/t/file_creation.test
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_example_key_management_plugin.inc
|
||||||
|
|
||||||
|
# embedded does not support restart
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# MDEV-19348 MariaBackup prepare fails with InnoDB: Database page corruption
|
||||||
|
# on disk or a failed file read
|
||||||
|
#
|
||||||
|
|
||||||
|
SET GLOBAL innodb_encrypt_tables = ON;
|
||||||
|
SET GLOBAL innodb_encryption_threads = 1;
|
||||||
|
SET GLOBAL innodb_max_dirty_pages_pct = 99;
|
||||||
|
SHOW VARIABLES LIKE 'innodb_encrypt%';
|
||||||
|
|
||||||
|
CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(255), f3 CHAR(255),
|
||||||
|
f4 CHAR(255), f5 CHAR(255))ENGINE=INNODB;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(1, "mysql", "mariadb", "batman", "superman");
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1;
|
||||||
|
|
||||||
|
--let $tables_count= `select count(*) + 1 from information_schema.tables where engine = 'InnoDB'`
|
||||||
|
|
||||||
|
--echo # Wait max 10 min for key encryption threads to encrypt all spaces
|
||||||
|
--let $wait_timeout= 600
|
||||||
|
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
|
||||||
|
--source ../../suite/innodb/include/no_checkpoint_start.inc
|
||||||
|
ALTER TABLE t1 FORCE;
|
||||||
|
--let CLEANUP_IF_CHECKPOINT=DROP TABLE t1;
|
||||||
|
--source ../../suite/innodb/include/no_checkpoint_end.inc
|
||||||
|
|
||||||
|
--source include/start_mysqld.inc
|
||||||
|
DROP TABLE t1;
|
@ -356,6 +356,33 @@ fil_space_destroy_crypt_data(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fill crypt data information to the give page.
|
||||||
|
It should be called during ibd file creation.
|
||||||
|
@param[in] flags tablespace flags
|
||||||
|
@param[in,out] page first page of the tablespace */
|
||||||
|
void
|
||||||
|
fil_space_crypt_t::fill_page0(
|
||||||
|
ulint flags,
|
||||||
|
byte* page)
|
||||||
|
{
|
||||||
|
const uint len = sizeof(iv);
|
||||||
|
const ulint offset = FSP_HEADER_OFFSET
|
||||||
|
+ fsp_header_get_encryption_offset(page_size_t(flags));
|
||||||
|
page0_offset = offset;
|
||||||
|
|
||||||
|
memcpy(page + offset, CRYPT_MAGIC, MAGIC_SZ);
|
||||||
|
mach_write_to_1(page + offset + MAGIC_SZ, type);
|
||||||
|
mach_write_to_1(page + offset + MAGIC_SZ + 1, len);
|
||||||
|
memcpy(page + offset + MAGIC_SZ + 2, &iv, len);
|
||||||
|
|
||||||
|
mach_write_to_4(page + offset + MAGIC_SZ + 2 + len,
|
||||||
|
min_key_version);
|
||||||
|
mach_write_to_4(page + offset + MAGIC_SZ + 2 + len + 4,
|
||||||
|
key_id);
|
||||||
|
mach_write_to_1(page + offset + MAGIC_SZ + 2 + len + 8,
|
||||||
|
encryption);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Write crypt data to a page (0)
|
Write crypt data to a page (0)
|
||||||
@param[in] space tablespace
|
@param[in] space tablespace
|
||||||
|
@ -3671,6 +3671,19 @@ fil_ibd_create(
|
|||||||
fsp_header_init_fields(page, space_id, flags);
|
fsp_header_init_fields(page, space_id, flags);
|
||||||
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
|
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
|
||||||
|
|
||||||
|
/* Create crypt data if the tablespace is either encrypted or user has
|
||||||
|
requested it to remain unencrypted. */
|
||||||
|
if (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF ||
|
||||||
|
srv_encrypt_tables) {
|
||||||
|
crypt_data = fil_space_create_crypt_data(mode, key_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crypt_data) {
|
||||||
|
/* Write crypt data information in page0 while creating
|
||||||
|
ibd file. */
|
||||||
|
crypt_data->fill_page0(flags, page);
|
||||||
|
}
|
||||||
|
|
||||||
const page_size_t page_size(flags);
|
const page_size_t page_size(flags);
|
||||||
IORequest request(IORequest::WRITE);
|
IORequest request(IORequest::WRITE);
|
||||||
|
|
||||||
@ -3732,13 +3745,6 @@ fil_ibd_create(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create crypt data if the tablespace is either encrypted or user has
|
|
||||||
requested it to remain unencrypted. */
|
|
||||||
if (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF ||
|
|
||||||
srv_encrypt_tables) {
|
|
||||||
crypt_data = fil_space_create_crypt_data(mode, key_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE,
|
space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE,
|
||||||
crypt_data, mode);
|
crypt_data, mode);
|
||||||
if (!space) {
|
if (!space) {
|
||||||
|
@ -180,6 +180,12 @@ struct fil_space_crypt_t : st_encryption_scheme
|
|||||||
return (encryption == FIL_ENCRYPTION_OFF);
|
return (encryption == FIL_ENCRYPTION_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fill crypt data information to the give page.
|
||||||
|
It should be called during ibd file creation.
|
||||||
|
@param[in] flags tablespace flags
|
||||||
|
@param[in,out] page first page of the tablespace */
|
||||||
|
void fill_page0(ulint flags, byte* page);
|
||||||
|
|
||||||
/** Write crypt data to a page (0)
|
/** Write crypt data to a page (0)
|
||||||
@param[in] space tablespace
|
@param[in] space tablespace
|
||||||
@param[in,out] page0 first page of the tablespace
|
@param[in,out] page0 first page of the tablespace
|
||||||
|
Loading…
x
Reference in New Issue
Block a user