Skip to content

Commit

Permalink
MDEV-15563: Instantly change a column to NULL
Browse files Browse the repository at this point in the history
Allow instant changes of columns in ROW_FORMAT=REDUNDANT
from NOT NULL to NULL.

Later, this may be implemented for ROW_FORMAT=COMPACT or DYNAMIC,
but in that case any indexes on the table must be rebuilt.

dict_table_t::prepare_instant(): Add some debug assertions,
and relax a debug assertion so that the number of fields is
allowed not to change.

dict_index_t::instant_add_field(): Relax a debug assertion,
allowing a column to change from NOT NULL to NULL.

dict_table_t::instant_column(): Add debug assertions.

instant_alter_column_possible(): Allow ALTER_COLUMN_NULLABLE
when applicable.

innodb_insert_sys_columns(): Add the parameter bool update=false
to run UPDATE instead of INSERT.

innobase_instant_add_col(): Remove; let the only caller invoke
innodb_insert_sys_columns() directly.

innobase_instant_try(): Update the SYS_COLUMNS record if the
column is changed. Only convert the table to the instant ALTER TABLE
format if necessary. For ALTER_COLUMN_NULLABLE in ROW_FORMAT=REDUNDANT,
there is no data format change.
  • Loading branch information
dr-m committed Dec 13, 2018
1 parent 62d28f8 commit 7a27db7
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 46 deletions.
11 changes: 10 additions & 1 deletion mysql-test/suite/innodb/r/instant_alter.result
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ INSERT INTO t1 VALUES
(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a');
ALTER TABLE t1 DROP COLUMN f1;
DROP TABLE t1;
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
Expand Down Expand Up @@ -1170,6 +1173,9 @@ INSERT INTO t1 VALUES
(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a');
ALTER TABLE t1 DROP COLUMN f1;
DROP TABLE t1;
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
Expand Down Expand Up @@ -1728,10 +1734,13 @@ INSERT INTO t1 VALUES
(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a');
ALTER TABLE t1 DROP COLUMN f1;
DROP TABLE t1;
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
disconnect analyze;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
117
120
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
56 changes: 56 additions & 0 deletions mysql-test/suite/innodb/r/instant_alter_null.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
create table t (a int NOT NULL) engine=innodb row_format= compressed;
alter table t modify a int NULL, algorithm=instant;
ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
drop table t;
create table t (a int NOT NULL) engine=innodb row_format= dynamic;
alter table t modify a int NULL, algorithm=instant;
ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
drop table t;
create table t (a int NOT NULL) engine=innodb row_format= compact;
alter table t modify a int NULL, algorithm=instant;
ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
drop table t;
create table t (
id int primary key,
a int NOT NULL default 0,
b int NOT NULL default 0,
c int NOT NULL default 0,
index idx (a,b,c)
) engine=innodb row_format=redundant;
insert into t (id, a) values (0, NULL);
ERROR 23000: Column 'a' cannot be null
insert into t (id, b) values (0, NULL);
ERROR 23000: Column 'b' cannot be null
insert into t (id, c) values (0, NULL);
ERROR 23000: Column 'c' cannot be null
insert into t values (1,1,1,1);
set @id = (select table_id from information_schema.innodb_sys_tables
where name = 'test/t');
select * from information_schema.innodb_sys_columns where table_id=@id;
TABLE_ID NAME POS MTYPE PRTYPE LEN
TABLE_ID id 0 6 1283 4
TABLE_ID a 1 6 1283 4
TABLE_ID b 2 6 1283 4
TABLE_ID c 3 6 1283 4
alter table t modify a int NULL, algorithm=instant;
insert into t values (2, NULL, 2, 2);
alter table t modify b int NULL, algorithm=nocopy;
insert into t values (3, NULL, NULL, 3);
alter table t modify c int NULL, algorithm=inplace;
insert into t values (4, NULL, NULL, NULL);
select * from information_schema.innodb_sys_columns where table_id=@id;
TABLE_ID NAME POS MTYPE PRTYPE LEN
TABLE_ID id 0 6 1283 4
TABLE_ID a 1 6 1027 4
TABLE_ID b 2 6 1027 4
TABLE_ID c 3 6 1027 4
select * from t;
id a b c
4 NULL NULL NULL
3 NULL NULL 3
2 NULL 2 2
1 1 1 1
check table t;
Table Op Msg_type Msg_text
test.t check status OK
drop table t;
4 changes: 4 additions & 0 deletions mysql-test/suite/innodb/t/instant_alter.test
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ INSERT INTO t1 VALUES
ALTER TABLE t1 DROP COLUMN f1;
DROP TABLE t1;

eval CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) $engine;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;

dec $format;
}
disconnect analyze;
Expand Down
57 changes: 57 additions & 0 deletions mysql-test/suite/innodb/t/instant_alter_null.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
--source include/have_innodb.inc

create table t (a int NOT NULL) engine=innodb row_format= compressed;
--error ER_ALTER_OPERATION_NOT_SUPPORTED
alter table t modify a int NULL, algorithm=instant;
drop table t;

create table t (a int NOT NULL) engine=innodb row_format= dynamic;
--error ER_ALTER_OPERATION_NOT_SUPPORTED
alter table t modify a int NULL, algorithm=instant;
drop table t;

create table t (a int NOT NULL) engine=innodb row_format= compact;
--error ER_ALTER_OPERATION_NOT_SUPPORTED
alter table t modify a int NULL, algorithm=instant;
drop table t;

create table t (
id int primary key,
a int NOT NULL default 0,
b int NOT NULL default 0,
c int NOT NULL default 0,
index idx (a,b,c)
) engine=innodb row_format=redundant;

--error ER_BAD_NULL_ERROR
insert into t (id, a) values (0, NULL);
--error ER_BAD_NULL_ERROR
insert into t (id, b) values (0, NULL);
--error ER_BAD_NULL_ERROR
insert into t (id, c) values (0, NULL);

insert into t values (1,1,1,1);

set @id = (select table_id from information_schema.innodb_sys_tables
where name = 'test/t');

--replace_column 1 TABLE_ID
select * from information_schema.innodb_sys_columns where table_id=@id;

alter table t modify a int NULL, algorithm=instant;
insert into t values (2, NULL, 2, 2);

alter table t modify b int NULL, algorithm=nocopy;
insert into t values (3, NULL, NULL, 3);

alter table t modify c int NULL, algorithm=inplace;
insert into t values (4, NULL, NULL, NULL);

--replace_column 1 TABLE_ID
select * from information_schema.innodb_sys_columns where table_id=@id;

select * from t;

check table t;

drop table t;
Loading

0 comments on commit 7a27db7

Please sign in to comment.