mirror of
https://github.com/MariaDB/server.git
synced 2025-10-12 12:25:37 +03:00
Allow ALGORITHM=INSTANT (or avoid touching any data) when changing the collation, or in some cases, the character set, of a non-indexed CHAR or VARCHAR column. There is no penalty for subsequent DDL or DML operations, and compatibility with older MariaDB versions will be unaffected. Character sets may be changed when the old encoding is compatible with the new one. For example, changing from ASCII to anything ASCII-based, or from 3-byte to 4-byte UTF-8 can sometimes be performed instantly. This is joint work with Eugene Kosov. The test cases as well as ALTER_CONVERT_TO, charsets_are_compatible(), Type_handler::Charsets_are_compatible() are his work. The Field_str::is_equal(), Field_varstring::is_equal() and the InnoDB changes were mostly rewritten by me due to conflicts with MDEV-15563. Limitations: Changes of indexed columns will still require ALGORITHM=COPY. We should allow ALGORITHM=NOCOPY and allow the indexes to be rebuilt inside the storage engine, without copying the entire table. Instant column size changes (in bytes) are not supported by all storage engines. Instant CHAR column changes are only allowed for InnoDB ROW_FORMAT=REDUNDANT. We could allow this for InnoDB when the CHAR internally uses a variable-length encoding, say, when converting from 3-byte UTF-8 to 4-byte UTF-8. Instant VARCHAR column changes are allowed for InnoDB ROW_FORMAT=REDUNDANT, and for others only if the size in bytes does not change from 128..255 bytes to more than 256 bytes. Inside InnoDB, this slightly changes the way how MDEV-15563 works and fixes the result of the innodb.instant_alter_extend test. We change the way how ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT is handled. All column extension, type changes and renaming now go through a common route, except when ctx->is_instant() is in effect, for example, instant ADD or DROP COLUMN has been initiated. Only in that case we will go through innobase_instant_try() and rewrite all column metadata. get_type(field, prtype, mtype, len): Convert a SQL data type into InnoDB column metadata. innobase_rename_column_try(): Remove the update of SYS_COLUMNS. innobase_rename_or_enlarge_column_try(): New function, replacing part of innobase_rename_column_try() and all of innobase_enlarge_column_try(). Also changes column types. innobase_rename_or_enlarge_columns_cache(): Also change the column type.
236 lines
7.6 KiB
Plaintext
236 lines
7.6 KiB
Plaintext
#
|
|
# MDEV-15563: Instant ROW_FORMAT=REDUNDANT column type change&extension
|
|
#
|
|
create or replace database test;
|
|
use test;
|
|
set default_storage_engine=innodb;
|
|
set @save_format= @@GLOBAL.innodb_default_row_format;
|
|
SET GLOBAL innodb_default_row_format=redundant;
|
|
set @bigval= repeat('0123456789', 30);
|
|
create or replace procedure check_table(table_name varchar(255))
|
|
begin
|
|
select table_id into @table_id
|
|
from information_schema.innodb_sys_tables
|
|
where name = concat('test/', table_name);
|
|
select name, mtype, hex(prtype) as prtype, len
|
|
from information_schema.innodb_sys_columns
|
|
where table_id = @table_id;
|
|
end~~
|
|
# VARCHAR -> CHAR, VARBINARY -> BINARY conversion
|
|
set @bigval= repeat('0123456789', 20);
|
|
create or replace table t (a varchar(300));
|
|
alter table t modify a char(255), algorithm=instant;
|
|
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
|
|
alter table t modify a char(255), algorithm=copy;
|
|
create or replace table t (a varchar(200));
|
|
insert into t values (@bigval);
|
|
insert into t values ('z');
|
|
alter table t modify a char(200), algorithm=instant;
|
|
select count(a) from t where a = @bigval;
|
|
count(a)
|
|
1
|
|
select a, length(a) from t where a = 'z';
|
|
a length(a)
|
|
z 1
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
a 2 800FE 200
|
|
# CHAR enlargement
|
|
alter table t modify a char(220), algorithm=instant;
|
|
select count(a) from t where a = @bigval;
|
|
count(a)
|
|
1
|
|
select a, length(a) from t where a = 'z';
|
|
a length(a)
|
|
z 1
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
a 2 800FE 220
|
|
# Convert from VARCHAR to a bigger CHAR
|
|
alter table t modify a varchar(200), algorithm=instant;
|
|
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
|
|
alter table t modify a varchar(200), algorithm=copy;
|
|
alter table t modify a char(255), algorithm=instant;
|
|
select count(a) from t where a = @bigval;
|
|
count(a)
|
|
1
|
|
select a, length(a) from t where a = 'z';
|
|
a length(a)
|
|
z 1
|
|
select * from t;
|
|
a
|
|
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
|
z
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
a 2 800FE 255
|
|
# BINARY/VARBINARY test
|
|
create or replace table t (a varbinary(300));
|
|
alter table t modify a binary(255), algorithm=instant;
|
|
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
|
|
alter table t modify a binary(255), algorithm=copy;
|
|
create or replace table t (a varbinary(200));
|
|
insert into t values (@bigval);
|
|
insert into t values ('z');
|
|
alter table t modify a binary(200), algorithm=instant;
|
|
select count(a) from t where a = @bigval;
|
|
count(a)
|
|
1
|
|
select length(a) from t where left(a, 1) = 'z';
|
|
length(a)
|
|
200
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
a 3 3F04FE 200
|
|
# BINARY enlargement
|
|
alter table t modify a binary(220), algorithm=instant;
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
a 3 3F04FE 220
|
|
# Convert from VARBINARY to a bigger BINARY
|
|
alter table t modify a varbinary(220), algorithm=instant;
|
|
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
|
|
alter table t modify a varbinary(220), algorithm=copy;
|
|
alter table t modify a binary(255), algorithm=instant;
|
|
select count(a) from t where a = @bigval;
|
|
count(a)
|
|
0
|
|
select a, length(a) from t where a = 'z';
|
|
a length(a)
|
|
select * from t;
|
|
a
|
|
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
|
z
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
a 3 3F04FE 255
|
|
# Integer conversions
|
|
create or replace table t (x tinyint);
|
|
insert into t values (127);
|
|
alter table t modify x smallint, algorithm=instant;
|
|
select * from t;
|
|
x
|
|
127
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
x 6 402 2
|
|
update t set x= 32767;
|
|
alter table t modify x mediumint, algorithm=instant;
|
|
select * from t;
|
|
x
|
|
32767
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
x 6 409 3
|
|
update t set x= 8388607;
|
|
alter table t modify x int, algorithm=instant;
|
|
select * from t;
|
|
x
|
|
8388607
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
x 6 403 4
|
|
update t set x= 2147483647;
|
|
alter table t modify x bigint, algorithm=instant;
|
|
select * from t;
|
|
x
|
|
2147483647
|
|
check table t extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t check status OK
|
|
call check_table('t');
|
|
name mtype prtype len
|
|
x 6 408 8
|
|
# Check IMPORT TABLESPACE
|
|
create or replace table t2 (x int);
|
|
alter table t2 discard tablespace;
|
|
create or replace table t1 (x tinyint);
|
|
insert into t1 set x= 42;
|
|
alter table t1 modify x int;
|
|
flush tables t1 for export;
|
|
unlock tables;
|
|
alter table t2 import tablespace;
|
|
select * from t2;
|
|
x
|
|
42
|
|
check table t2 extended;
|
|
Table Op Msg_type Msg_text
|
|
test.t2 check status OK
|
|
call check_table('t2');
|
|
name mtype prtype len
|
|
x 6 403 4
|
|
# Check innobase_col_to_mysql() len < flen
|
|
create or replace table t1 (x mediumint);
|
|
insert into t1 values (1);
|
|
insert into t1 values (1);
|
|
alter table t1 add column y int first, modify x int, algorithm instant;
|
|
alter table t1 add column z int first, add primary key (x);
|
|
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
|
# Check assertion in wrong instant operation
|
|
create or replace table t1 (a varchar(26) not null) default character set utf8mb4;
|
|
alter table t1 modify a varchar(25) not null;
|
|
# Check row_mysql_store_col_in_innobase_format()
|
|
create or replace table t1(x int primary key, a varchar(20));
|
|
insert into t1 (x) values (1);
|
|
update t1 set a= 'foo' where x = 2;
|
|
#
|
|
# MDEV-18124 PK on inplace-enlarged type fails
|
|
#
|
|
create or replace table t1 (x int, y int);
|
|
insert into t1 (x, y) values (11, 22);
|
|
alter table t1 modify x bigint, algorithm instant;
|
|
alter table t1 add primary key (x), algorithm inplace;
|
|
check table t1;
|
|
Table Op Msg_type Msg_text
|
|
test.t1 check status OK
|
|
create or replace table t1 (a varchar(10), y int);
|
|
insert into t1 (a, y) values ("0123456789", 33);
|
|
alter table t1 modify a char(15), algorithm instant;
|
|
alter table t1 add primary key (a), algorithm inplace;
|
|
check table t1;
|
|
Table Op Msg_type Msg_text
|
|
test.t1 check status OK
|
|
create or replace table t1 (x int primary key, y int);
|
|
insert into t1 (x, y) values (44, 55);
|
|
alter table t1 modify x bigint, algorithm inplace;
|
|
check table t1;
|
|
Table Op Msg_type Msg_text
|
|
test.t1 check status OK
|
|
create or replace table t1 (x int primary key, y int);
|
|
insert into t1 values (66, 77);
|
|
alter table t1 add column z int, algorithm instant;
|
|
alter table t1 drop column y, algorithm instant;
|
|
create or replace table t1 (x integer, a varchar(20));
|
|
alter table t1 add index idx3 (a);
|
|
insert into t1 (x, a) values (73, 'a');
|
|
alter table t1 modify a char(20);
|
|
create or replace database test charset latin1;
|
|
SET GLOBAL innodb_default_row_format=@save_format;
|