From 88edb1b3edcea0dad82659ca6622448e535a3fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 30 Oct 2017 18:47:43 +0200 Subject: [PATCH] MDEV-14219 Allow online table rebuild when encryption or compression parameters change When MariaDB 10.1.0 introduced table options for encryption and compression, it unnecessarily changed ha_innobase::check_if_supported_inplace_alter() so that ALGORITHM=COPY is forced when these parameters differ. A better solution is to move the check to innobase_need_rebuild(). In that way, the ALGORITHM=INPLACE interface (yes, the syntax is very misleading) can be used for rebuilding the table much more efficiently, with merge sort, with no undo logging, and allowing concurrent DML operations. --- .../encryption/r/encryption_force.result | 4 +- .../encryption/r/filekeys_encfile.result | 2 +- .../encryption/r/filekeys_encfile_file.result | 2 +- .../r/innodb-encryption-alter.result | 5 +- .../suite/encryption/t/encryption_force.test | 6 +- .../suite/encryption/t/filekeys_goodtest.inc | 4 +- .../encryption/t/innodb-encryption-alter.test | 4 +- .../r/innodb-page_compression_tables.result | 5 +- .../suite/innodb/r/innodb-table-online.result | 6 +- .../t/innodb-page_compression_tables.test | 4 +- .../suite/innodb/t/innodb-table-online.test | 7 +- storage/innobase/handler/handler0alter.cc | 88 ++++++++++--------- storage/xtradb/handler/handler0alter.cc | 88 ++++++++++--------- 13 files changed, 116 insertions(+), 109 deletions(-) diff --git a/mysql-test/suite/encryption/r/encryption_force.result b/mysql-test/suite/encryption/r/encryption_force.result index de5f7da60a8..9d42b360e7c 100644 --- a/mysql-test/suite/encryption/r/encryption_force.result +++ b/mysql-test/suite/encryption/r/encryption_force.result @@ -34,11 +34,11 @@ t4 CREATE TABLE `t4` ( /*!50100 PARTITION BY HASH (a) PARTITIONS 2 */ alter table t1 encrypted=no; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTED' alter table t2 encrypted=yes; alter table t3 encrypted=default; alter table t4 encrypted=no; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTED' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/encryption/r/filekeys_encfile.result b/mysql-test/suite/encryption/r/filekeys_encfile.result index add6f312fda..6d5baa1b7ff 100644 --- a/mysql-test/suite/encryption/r/filekeys_encfile.result +++ b/mysql-test/suite/encryption/r/filekeys_encfile.result @@ -14,7 +14,7 @@ t1 CREATE TABLE `t1` ( `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `encrypted`=yes `encryption_key_id`=2 alter table t1 encryption_key_id=3; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/encryption/r/filekeys_encfile_file.result b/mysql-test/suite/encryption/r/filekeys_encfile_file.result index add6f312fda..6d5baa1b7ff 100644 --- a/mysql-test/suite/encryption/r/filekeys_encfile_file.result +++ b/mysql-test/suite/encryption/r/filekeys_encfile_file.result @@ -14,7 +14,7 @@ t1 CREATE TABLE `t1` ( `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `encrypted`=yes `encryption_key_id`=2 alter table t1 encryption_key_id=3; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/encryption/r/innodb-encryption-alter.result b/mysql-test/suite/encryption/r/innodb-encryption-alter.result index 5869c5d7000..9ff0f492034 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-alter.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-alter.result @@ -43,11 +43,10 @@ CREATE TABLE t2 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNOD Warnings: Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 1 when encryption is disabled ALTER TABLE t1 ENCRYPTION_KEY_ID=99; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' SHOW WARNINGS; Level Code Message Warning 140 InnoDB: ENCRYPTION_KEY_ID 99 not available -Error 1005 Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +Error 1478 Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' set innodb_default_encryption_key_id = 1; drop table t1,t2; diff --git a/mysql-test/suite/encryption/t/encryption_force.test b/mysql-test/suite/encryption/t/encryption_force.test index 3e09dd91839..3c6f039184b 100644 --- a/mysql-test/suite/encryption/t/encryption_force.test +++ b/mysql-test/suite/encryption/t/encryption_force.test @@ -22,13 +22,11 @@ show create table t2; show create table t3; show create table t4; ---replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ ---error ER_CANT_CREATE_TABLE +--error ER_ILLEGAL_HA_CREATE_OPTION alter table t1 encrypted=no; alter table t2 encrypted=yes; alter table t3 encrypted=default; ---replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ ---error ER_CANT_CREATE_TABLE +--error ER_ILLEGAL_HA_CREATE_OPTION alter table t4 encrypted=no; show create table t1; diff --git a/mysql-test/suite/encryption/t/filekeys_goodtest.inc b/mysql-test/suite/encryption/t/filekeys_goodtest.inc index 146a570412c..5317eeb3d12 100644 --- a/mysql-test/suite/encryption/t/filekeys_goodtest.inc +++ b/mysql-test/suite/encryption/t/filekeys_goodtest.inc @@ -7,8 +7,7 @@ insert t1 values (12345, repeat('1234567890', 20)); alter table t1 encryption_key_id=2; show create table t1; ---replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ ---error ER_CANT_CREATE_TABLE +--error ER_ILLEGAL_HA_CREATE_OPTION alter table t1 encryption_key_id=3; show create table t1; alter table t1 encryption_key_id=33; @@ -17,4 +16,3 @@ alter table t1 encryption_key_id=4; show create table t1; drop table t1; - diff --git a/mysql-test/suite/encryption/t/innodb-encryption-alter.test b/mysql-test/suite/encryption/t/innodb-encryption-alter.test index 316ece1c16b..9420fb74a4c 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-alter.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-alter.test @@ -33,10 +33,8 @@ DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; SHOW CREATE TABLE t1; CREATE TABLE t2 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=1; ---replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ ---error 1005 +--error ER_ILLEGAL_HA_CREATE_OPTION ALTER TABLE t1 ENCRYPTION_KEY_ID=99; ---replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ SHOW WARNINGS; set innodb_default_encryption_key_id = 1; diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_tables.result b/mysql-test/suite/innodb/r/innodb-page_compression_tables.result index 98de5db3c12..072f1d1e440 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_tables.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_tables.result @@ -38,12 +38,11 @@ innodb_redundant CREATE TABLE `innodb_redundant` ( `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT alter table innodb_redundant page_compressed=1; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'PAGE_COMPRESSED' show warnings; Level Code Message Warning 140 InnoDB: PAGE_COMPRESSED table can't have ROW_TYPE=REDUNDANT -Error 1005 Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +Error 1478 Table storage engine 'InnoDB' does not support the create option 'PAGE_COMPRESSED' show create table innodb_redundant; Table Create Table innodb_redundant CREATE TABLE `innodb_redundant` ( diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result index cc4df79c10a..9b1097b3afa 100644 --- a/mysql-test/suite/innodb/r/innodb-table-online.result +++ b/mysql-test/suite/innodb/r/innodb-table-online.result @@ -3,6 +3,8 @@ call mtr.add_suppression("InnoDB: Error: table 'test/t1'"); call mtr.add_suppression("MySQL is trying to open a table handle but the .ibd file for"); SET @global_innodb_file_per_table_orig = @@global.innodb_file_per_table; SET GLOBAL innodb_file_per_table = on; +SET @file_format = @@GLOBAL.innodb_file_format; +SET GLOBAL innodb_file_format = Barracuda; CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 CHAR(255) NOT NULL) ENGINE = InnoDB; INSERT INTO t1 VALUES (1,1,''), (2,2,''), (3,3,''), (4,4,''), (5,5,''); @@ -203,7 +205,8 @@ t1 CREATE TABLE `t1` ( ALTER TABLE t1 ROW_FORMAT=REDUNDANT; SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL rebuilt2 WAIT_FOR dml2_done'; SET lock_wait_timeout = 10; -ALTER TABLE t1 ROW_FORMAT=COMPACT, ALGORITHM = INPLACE; +ALTER TABLE t1 ROW_FORMAT=COMPACT +PAGE_COMPRESSED = YES PAGE_COMPRESSION_LEVEL = 1, ALGORITHM = INPLACE; # session default INSERT INTO t1 SELECT 80 + c1, c2, c3 FROM t1; INSERT INTO t1 SELECT 160 + c1, c2, c3 FROM t1; @@ -438,5 +441,6 @@ SET DEBUG_SYNC = 'RESET'; SET GLOBAL innodb_monitor_disable = module_ddl; DROP TABLE t1; SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig; +SET GLOBAL innodb_file_format = @file_format; SET GLOBAL innodb_monitor_enable = default; SET GLOBAL innodb_monitor_disable = default; diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_tables.test b/mysql-test/suite/innodb/t/innodb-page_compression_tables.test index 41d844d26b4..d8a85d7f273 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_tables.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_tables.test @@ -32,10 +32,8 @@ create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row show warnings; create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant; show create table innodb_redundant; ---replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/ ---error 1005 +--error ER_ILLEGAL_HA_CREATE_OPTION alter table innodb_redundant page_compressed=1; ---replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/ show warnings; show create table innodb_redundant; alter table innodb_redundant row_format=compact page_compressed=1; diff --git a/mysql-test/suite/innodb/t/innodb-table-online.test b/mysql-test/suite/innodb/t/innodb-table-online.test index 938025359c5..b9c9dc085d6 100644 --- a/mysql-test/suite/innodb/t/innodb-table-online.test +++ b/mysql-test/suite/innodb/t/innodb-table-online.test @@ -14,6 +14,9 @@ call mtr.add_suppression("MySQL is trying to open a table handle but the .ibd fi # DISCARD TABLESPACE needs file-per-table SET @global_innodb_file_per_table_orig = @@global.innodb_file_per_table; SET GLOBAL innodb_file_per_table = on; +# PAGE_COMPRESSED needs innodb_file_format!=Antelope +SET @file_format = @@GLOBAL.innodb_file_format; +SET GLOBAL innodb_file_format = Barracuda; # Save the initial number of concurrent sessions. --source include/count_sessions.inc @@ -215,7 +218,8 @@ SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL rebuilt2 WAIT_FOR dml2_done # Ensure that the ALTER TABLE will be executed even with some concurrent DML. SET lock_wait_timeout = 10; --send -ALTER TABLE t1 ROW_FORMAT=COMPACT, ALGORITHM = INPLACE; +ALTER TABLE t1 ROW_FORMAT=COMPACT +PAGE_COMPRESSED = YES PAGE_COMPRESSION_LEVEL = 1, ALGORITHM = INPLACE; # Generate some log (delete-mark, delete-unmark, insert etc.) # while the index creation is blocked. Some of this may run @@ -443,6 +447,7 @@ DROP TABLE t1; --source include/wait_until_count_sessions.inc SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig; +SET GLOBAL innodb_file_format = @file_format; --disable_warnings SET GLOBAL innodb_monitor_enable = default; SET GLOBAL innodb_monitor_disable = default; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index a1f0fbb1e7e..bdc4987b5c9 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -208,32 +208,44 @@ innobase_fulltext_exist( return(false); } -/*******************************************************************//** -Determine if ALTER TABLE needs to rebuild the table. -@param ha_alter_info the DDL operation -@param altered_table MySQL original table +/** Determine if ALTER TABLE needs to rebuild the table. +@param ha_alter_info the DDL operation +@param table metadata before ALTER TABLE @return whether it is necessary to rebuild the table */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) bool innobase_need_rebuild( -/*==================*/ const Alter_inplace_info* ha_alter_info, - const TABLE* altered_table) + const TABLE* table) { Alter_inplace_info::HA_ALTER_FLAGS alter_inplace_flags = - ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE); + ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE; - if (alter_inplace_flags - == Alter_inplace_info::CHANGE_CREATE_OPTION + if (alter_inplace_flags & Alter_inplace_info::CHANGE_CREATE_OPTION) { + const ha_table_option_struct& alt_opt= + *ha_alter_info->create_info->option_struct; + const ha_table_option_struct& opt= *table->s->option_struct; + + if (alt_opt.page_compressed != opt.page_compressed + || alt_opt.page_compression_level + != opt.page_compression_level + || alt_opt.encryption != opt.encryption + || alt_opt.encryption_key_id != opt.encryption_key_id) { + return(true); + } + } + + if (alter_inplace_flags == Alter_inplace_info::CHANGE_CREATE_OPTION && !(ha_alter_info->create_info->used_fields & (HA_CREATE_USED_ROW_FORMAT | HA_CREATE_USED_KEY_BLOCK_SIZE))) { /* Any other CHANGE_CREATE_OPTION than changing - ROW_FORMAT or KEY_BLOCK_SIZE is ignored. */ + ROW_FORMAT or KEY_BLOCK_SIZE can be done without + rebuilding the table. */ return(false); } - return(!!(ha_alter_info->handler_flags & INNOBASE_ALTER_REBUILD)); + return(!!(alter_inplace_flags & INNOBASE_ALTER_REBUILD)); } /** Check if InnoDB supports a particular alter table in-place @@ -283,29 +295,6 @@ ha_innobase::check_if_supported_inplace_alter( update_thd(); trx_search_latch_release_if_reserved(prebuilt->trx); - /* Change on engine specific table options require rebuild of the - table */ - if (ha_alter_info->handler_flags - & Alter_inplace_info::CHANGE_CREATE_OPTION) { - ha_table_option_struct *new_options= ha_alter_info->create_info->option_struct; - ha_table_option_struct *old_options= table->s->option_struct; - - if (new_options->page_compressed != old_options->page_compressed || - new_options->page_compression_level != old_options->page_compression_level || - new_options->atomic_writes != old_options->atomic_writes) { - ha_alter_info->unsupported_reason = innobase_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON); - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } - - if (new_options->encryption != old_options->encryption || - new_options->encryption_key_id != old_options->encryption_key_id) { - ha_alter_info->unsupported_reason = innobase_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON); - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } - } - if (ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_NOREBUILD @@ -584,7 +573,7 @@ ha_innobase::check_if_supported_inplace_alter( operation is possible. */ } else if (((ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - || innobase_need_rebuild(ha_alter_info, table)) + || innobase_need_rebuild(ha_alter_info, table)) && (innobase_fulltext_exist(altered_table))) { /* Refuse to rebuild the table online, if fulltext indexes are to survive the rebuild. */ @@ -2863,7 +2852,6 @@ prepare_inplace_alter_table_dict( to rebuild the table with a temporary name. */ if (new_clustered) { - fil_space_crypt_t* crypt_data; const char* new_table_name = dict_mem_create_temporary_tablename( ctx->heap, @@ -2874,13 +2862,29 @@ prepare_inplace_alter_table_dict( ulint key_id = FIL_DEFAULT_ENCRYPTION_KEY; fil_encryption_t mode = FIL_ENCRYPTION_DEFAULT; - fil_space_t* space = fil_space_acquire(ctx->prebuilt->table->space); - crypt_data = space->crypt_data; - fil_space_release(space); + if (fil_space_t* space + = fil_space_acquire(ctx->prebuilt->table->space)) { + if (const fil_space_crypt_t* crypt_data + = space->crypt_data) { + key_id = crypt_data->key_id; + mode = crypt_data->encryption; + } - if (crypt_data) { - key_id = crypt_data->key_id; - mode = crypt_data->encryption; + fil_space_release(space); + } + + if (ha_alter_info->handler_flags + & Alter_inplace_info::CHANGE_CREATE_OPTION) { + const ha_table_option_struct& alt_opt= + *ha_alter_info->create_info->option_struct; + const ha_table_option_struct& opt= + *old_table->s->option_struct; + if (alt_opt.encryption != opt.encryption + || alt_opt.encryption_key_id + != opt.encryption_key_id) { + key_id = alt_opt.encryption_key_id; + mode = fil_encryption_t(alt_opt.encryption); + } } if (innobase_check_foreigns( diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 0842d11d178..b2f0d301815 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -212,32 +212,44 @@ innobase_fulltext_exist( return(false); } -/*******************************************************************//** -Determine if ALTER TABLE needs to rebuild the table. -@param ha_alter_info the DDL operation -@param altered_table MySQL original table +/** Determine if ALTER TABLE needs to rebuild the table. +@param ha_alter_info the DDL operation +@param table metadata before ALTER TABLE @return whether it is necessary to rebuild the table */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) bool innobase_need_rebuild( -/*==================*/ const Alter_inplace_info* ha_alter_info, - const TABLE* altered_table) + const TABLE* table) { Alter_inplace_info::HA_ALTER_FLAGS alter_inplace_flags = - ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE); + ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE; - if (alter_inplace_flags - == Alter_inplace_info::CHANGE_CREATE_OPTION + if (alter_inplace_flags & Alter_inplace_info::CHANGE_CREATE_OPTION) { + const ha_table_option_struct& alt_opt= + *ha_alter_info->create_info->option_struct; + const ha_table_option_struct& opt= *table->s->option_struct; + + if (alt_opt.page_compressed != opt.page_compressed + || alt_opt.page_compression_level + != opt.page_compression_level + || alt_opt.encryption != opt.encryption + || alt_opt.encryption_key_id != opt.encryption_key_id) { + return(true); + } + } + + if (alter_inplace_flags == Alter_inplace_info::CHANGE_CREATE_OPTION && !(ha_alter_info->create_info->used_fields & (HA_CREATE_USED_ROW_FORMAT | HA_CREATE_USED_KEY_BLOCK_SIZE))) { /* Any other CHANGE_CREATE_OPTION than changing - ROW_FORMAT or KEY_BLOCK_SIZE is ignored. */ + ROW_FORMAT or KEY_BLOCK_SIZE can be done without + rebuilding the table. */ return(false); } - return(!!(ha_alter_info->handler_flags & INNOBASE_ALTER_REBUILD)); + return(!!(alter_inplace_flags & INNOBASE_ALTER_REBUILD)); } /** Check if InnoDB supports a particular alter table in-place @@ -287,29 +299,6 @@ ha_innobase::check_if_supported_inplace_alter( update_thd(); trx_search_latch_release_if_reserved(prebuilt->trx); - /* Change on engine specific table options require rebuild of the - table */ - if (ha_alter_info->handler_flags - & Alter_inplace_info::CHANGE_CREATE_OPTION) { - ha_table_option_struct *new_options= ha_alter_info->create_info->option_struct; - ha_table_option_struct *old_options= table->s->option_struct; - - if (new_options->page_compressed != old_options->page_compressed || - new_options->page_compression_level != old_options->page_compression_level || - new_options->atomic_writes != old_options->atomic_writes) { - ha_alter_info->unsupported_reason = innobase_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON); - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } - - if (new_options->encryption != old_options->encryption || - new_options->encryption_key_id != old_options->encryption_key_id) { - ha_alter_info->unsupported_reason = innobase_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON); - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } - } - if (ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_NOREBUILD @@ -589,7 +578,7 @@ ha_innobase::check_if_supported_inplace_alter( operation is possible. */ } else if (((ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - || innobase_need_rebuild(ha_alter_info, table)) + || innobase_need_rebuild(ha_alter_info, table)) && (innobase_fulltext_exist(altered_table))) { /* Refuse to rebuild the table online, if fulltext indexes are to survive the rebuild. */ @@ -2870,7 +2859,6 @@ prepare_inplace_alter_table_dict( to rebuild the table with a temporary name. */ if (new_clustered) { - fil_space_crypt_t* crypt_data; const char* new_table_name = dict_mem_create_temporary_tablename( ctx->heap, @@ -2881,13 +2869,29 @@ prepare_inplace_alter_table_dict( ulint key_id = FIL_DEFAULT_ENCRYPTION_KEY; fil_encryption_t mode = FIL_ENCRYPTION_DEFAULT; - fil_space_t* space = fil_space_acquire(ctx->prebuilt->table->space); - crypt_data = space->crypt_data; - fil_space_release(space); + if (fil_space_t* space + = fil_space_acquire(ctx->prebuilt->table->space)) { + if (const fil_space_crypt_t* crypt_data + = space->crypt_data) { + key_id = crypt_data->key_id; + mode = crypt_data->encryption; + } - if (crypt_data) { - key_id = crypt_data->key_id; - mode = crypt_data->encryption; + fil_space_release(space); + } + + if (ha_alter_info->handler_flags + & Alter_inplace_info::CHANGE_CREATE_OPTION) { + const ha_table_option_struct& alt_opt= + *ha_alter_info->create_info->option_struct; + const ha_table_option_struct& opt= + *old_table->s->option_struct; + if (alt_opt.encryption != opt.encryption + || alt_opt.encryption_key_id + != opt.encryption_key_id) { + key_id = alt_opt.encryption_key_id; + mode = fil_encryption_t(alt_opt.encryption); + } } if (innobase_check_foreigns(