Skip to content

Commit

Permalink
[bugfix] Issue: #62 alter TokuDB table comment rebuild whole engine data
Browse files Browse the repository at this point in the history
Alter TokuDB table comment should not using copying algorithm and
rebuild whole engine data, only FRM definition should be changed.

Make `ha_tokudb::check_if_supported_inplace_alter()` return
`HA_ALTER_INPLACE_EXCLUSIVE_LOCK` while altering comment, and mysql
server will invoke `ha_tokudb::inplace_alter_table` which will do
nothing for altering comment.

Besides table comment, there are many other create options that
should be ignored by TokuDB, and they are all handled in this patch.

Btw, this patch has been pushed to TokuDB upstream.

This patch also contains a postfix for bug#88847, which handles
cases when UK or Key with auto-inc fileld is invisible.
  • Loading branch information
AliSQL authored and AliSQL committed May 1, 2018
1 parent 66c68db commit 349aa36
Show file tree
Hide file tree
Showing 4 changed files with 411 additions and 3 deletions.
186 changes: 186 additions & 0 deletions mysql-test/suite/rds/r/alter_table_comment_rebuild_data.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
create table t1(id int auto_increment, name varchar(30), primary key(id)) engine=TokuDB;
alter table t1 min_rows = 8;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=latin1 MIN_ROWS=8
include/assert.inc [underlying ft file name not changed after alter min_rows]
alter table t1 max_rows = 100;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=latin1 MIN_ROWS=8 MAX_ROWS=100
include/assert.inc [underlying ft file name not changed after alter max_rows]
alter table t1 avg_row_length = 100;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=latin1 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100
include/assert.inc [underlying ft file name not changed after alter avg_row_length]
alter table t1 pack_keys = 1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=latin1 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1
include/assert.inc [underlying ft file name not changed after alter pack_keys]
alter table t1 character set = utf8;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1
include/assert.inc [underlying ft file name not changed after alter character set]
alter table t1 data directory = '/tmp';
Warnings:
Warning 1618 <DATA DIRECTORY> option ignored
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1
include/assert.inc [underlying ft file name not changed after alter data directory]
alter table t1 index directory = '/tmp';
Warnings:
Warning 1618 <INDEX DIRECTORY> option ignored
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1
include/assert.inc [underlying ft file name not changed after alter index directory]
alter table t1 checksum = 1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 CHECKSUM=1
include/assert.inc [underlying ft file name not changed after alter checksum]
alter table t1 delay_key_write=1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1
include/assert.inc [underlying ft file name not changed after alter delay_key_write]
alter table t1 comment = 'test table';
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 COMMENT='test table'
include/assert.inc [underlying ft file name not changed after alter comment]
alter table t1 password = '123456';
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 COMMENT='test table'
include/assert.inc [underlying ft file name not changed after alter password]
alter table t1 connection = '127.0.0.1:3306';
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter connection]
alter table t1 key_block_size=32;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter key_block_size]
alter table t1 stats_persistent = 1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter stats_persistent]
alter table t1 stats_auto_recalc = 1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 STATS_AUTO_RECALC=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter stats_auto_recalc]
alter table t1 stats_sample_pages = 1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 STATS_AUTO_RECALC=1 STATS_SAMPLE_PAGES=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter stats_sample_pages]
alter table t1 auto_increment = 1000;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 STATS_AUTO_RECALC=1 STATS_SAMPLE_PAGES=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter auto_increment]
alter table t1 row_format=tokudb_lzma;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 STATS_AUTO_RECALC=1 STATS_SAMPLE_PAGES=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=TOKUDB_LZMA KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name not changed after alter compression method]
alter table t1 engine=TokuDB;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 STATS_AUTO_RECALC=1 STATS_SAMPLE_PAGES=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name changed after alter engine type]
alter table t1 convert to character set utf8;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 MIN_ROWS=8 MAX_ROWS=100 AVG_ROW_LENGTH=100 PACK_KEYS=1 STATS_PERSISTENT=1 STATS_AUTO_RECALC=1 STATS_SAMPLE_PAGES=1 CHECKSUM=1 DELAY_KEY_WRITE=1 KEY_BLOCK_SIZE=32 COMMENT='test table' CONNECTION='127.0.0.1:3306'
include/assert.inc [underlying ft file name changed after alter convert character]
drop table t1;
184 changes: 184 additions & 0 deletions mysql-test/suite/rds/t/alter_table_comment_rebuild_data.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
--source include/have_tokudb.inc

#
# Create a table and get the underlying main ft file name
#
create table t1(id int auto_increment, name varchar(30), primary key(id)) engine=TokuDB;
--let $ori_file= `select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`

#
# Case 1: alter create options that are ignored by TokuDB
#

# Alter table with min_rows
alter table t1 min_rows = 8;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter min_rows
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with max_rows
alter table t1 max_rows = 100;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter max_rows
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with avg_row_length
alter table t1 avg_row_length = 100;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter avg_row_length
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with pack_keys
alter table t1 pack_keys = 1;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter pack_keys
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with default character set
alter table t1 character set = utf8;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter character set
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with data directory
alter table t1 data directory = '/tmp';
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter data directory
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with index directory
alter table t1 index directory = '/tmp';
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter index directory
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with checksum
alter table t1 checksum = 1;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter checksum
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with delay_key_write
alter table t1 delay_key_write=1;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter delay_key_write
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with comment
alter table t1 comment = 'test table';
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter comment
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with password
alter table t1 password = '123456';
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter password
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with connection
alter table t1 connection = '127.0.0.1:3306';
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter connection
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with key_block_size
alter table t1 key_block_size=32;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter key_block_size
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with stats_persistent
alter table t1 stats_persistent = 1;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter stats_persistent
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with stats_auto_recalc
alter table t1 stats_auto_recalc = 1;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter stats_auto_recalc
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with stats_sample_pages
alter table t1 stats_sample_pages = 1;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter stats_sample_pages
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

#
# Case 2: alter create options that only update meta info, i.e inplace
#

# Alter table with auto_increment
alter table t1 auto_increment = 1000;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter auto_increment
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

# Alter table with compression method
alter table t1 row_format=tokudb_lzma;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name not changed after alter compression method
--let $assert_cond= "$ori_file" = "$new_file"
--source include/assert.inc

#
# Case 3: alter create options that rebuild table using copy algorithm
#

# Alter table with engine type
alter table t1 engine=TokuDB;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name changed after alter engine type
--let $assert_cond= "$ori_file" != "$new_file"
--source include/assert.inc

# Alter table with convert character
alter table t1 convert to character set utf8;
show create table t1;
--let $new_file=`select internal_file_name from information_schema.tokudb_file_map where table_schema='test' and table_name='t1' and table_dictionary_name='main'`
--let $assert_text= underlying ft file name changed after alter convert character
--let $assert_cond= "$ori_file" != "$new_file"
--source include/assert.inc

#
# clean up
#
drop table t1;
5 changes: 3 additions & 2 deletions sql/log_event.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9908,7 +9908,7 @@ search_key_in_table(TABLE *table, MY_BITMAP *bi_cols, uint key_type)
- Skip primary keys
*/
if (!((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
(key == table->s->primary_key))
(key == table->s->primary_key) || !(table->s->usable_indexes().is_set(key)))
continue;
res= are_all_columns_signaled_for_key(keyinfo, bi_cols) ?
key : MAX_KEY;
Expand All @@ -9924,7 +9924,8 @@ search_key_in_table(TABLE *table, MY_BITMAP *bi_cols, uint key_type)
DBUG_PRINT("debug", ("Searching for K."));

/* auot_increment index has higher priority over other secondary indexes */
if (table->found_next_number_field)
if (table->found_next_number_field &&
table->s->usable_indexes().is_set(table->s->next_number_index))
{
keyinfo= table->key_info + table->s->next_number_index;

Expand Down
Loading

0 comments on commit 349aa36

Please sign in to comment.