MDEV-13134 Introduce ALTER TABLE attributes ALGORITHM=NOCOPY and ALGORITHM=INSTANT

Introduced new alter algorithm type called NOCOPY & INSTANT for
inplace alter operation.

NOCOPY - Algorithm refuses any alter operation that would
rebuild the clustered index. It is a subset of INPLACE algorithm.

INSTANT - Algorithm allow any alter operation that would
modify only meta data. It is a subset of NOCOPY algorithm.

Introduce new variable called alter_algorithm. The values are
DEFAULT(0), COPY(1), INPLACE(2), NOCOPY(3), INSTANT(4)

Message to deprecate old_alter_table variable and make it alias
for alter_algorithm variable.

alter_algorithm variable for slave is always set to default.
This commit is contained in:
Thirunarayanan Balathandayuthapani 2018-05-07 14:54:58 +05:30
parent a0bc3b7eee
commit 85cc6b70bd
44 changed files with 1337 additions and 342 deletions

View File

@ -1810,9 +1810,7 @@ affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0 info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 ADD FULLTEXT INDEX ii3 (d); ALTER TABLE ti1 ADD FULLTEXT INDEX ii3 (d);
affected rows: 0 affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1 info: Records: 0 Duplicates: 0 Warnings: 0
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
ALTER TABLE tm1 ADD FULLTEXT INDEX im3 (d); ALTER TABLE tm1 ADD FULLTEXT INDEX im3 (d);
affected rows: 2 affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0 info: Records: 2 Duplicates: 0 Warnings: 0

View File

@ -112,7 +112,7 @@ create table t1 (a int not null primary key, b int, c varchar(80));
create table t2 (a int not null primary key, b int, c varchar(80)); create table t2 (a int not null primary key, b int, c varchar(80));
create table t3 (a int not null primary key, b int, c varchar(80)) engine=merge UNION=(t1); create table t3 (a int not null primary key, b int, c varchar(80)) engine=merge UNION=(t1);
alter online table t3 union=(t1,t2); alter online table t3 union=(t1,t2);
ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE ERROR 0A000: LOCK=NONE is not supported for this operation. Try LOCK=EXCLUSIVE
drop table t1,t2,t3; drop table t1,t2,t3;
create table t1 (i int) partition by hash(i) partitions 2; create table t1 (i int) partition by hash(i) partitions 2;
alter online table t1 comment 'test'; alter online table t1 comment 'test';

View File

@ -12,6 +12,9 @@ The following specify which files/extra groups are read (specified before remain
without corresponding xxx_init() or xxx_deinit(). That without corresponding xxx_init() or xxx_deinit(). That
also means that one can load any function from any also means that one can load any function from any
library, for example exit() from libc.so library, for example exit() from libc.so
--alter-algorithm[=name]
Specify the alter table algorithm. One of: DEFAULT, COPY,
INPLACE, NOCOPY, INSTANT
-a, --ansi Use ANSI SQL syntax instead of MySQL syntax. This mode -a, --ansi Use ANSI SQL syntax instead of MySQL syntax. This mode
will also set transaction isolation level 'serializable'. will also set transaction isolation level 'serializable'.
--auto-increment-increment[=#] --auto-increment-increment[=#]
@ -617,7 +620,10 @@ The following specify which files/extra groups are read (specified before remain
connection before aborting the write connection before aborting the write
--old Use compatible behavior from previous MariaDB version. --old Use compatible behavior from previous MariaDB version.
See also --old-mode See also --old-mode
--old-alter-table Use old, non-optimized alter table --old-alter-table[=name]
Alias for alter_algorithm. Deprecated. Use
--alter-algorithm instead.. One of: DEFAULT, COPY,
INPLACE, NOCOPY, INSTANT
--old-mode=name Used to emulate old behavior from earlier MariaDB or --old-mode=name Used to emulate old behavior from earlier MariaDB or
MySQL versions. Any combination of: MySQL versions. Any combination of:
NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO, NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO,
@ -1334,6 +1340,7 @@ The following specify which files/extra groups are read (specified before remain
Variables (--variable-name=value) Variables (--variable-name=value)
allow-suspicious-udfs FALSE allow-suspicious-udfs FALSE
alter-algorithm DEFAULT
auto-increment-increment 1 auto-increment-increment 1
auto-increment-offset 1 auto-increment-offset 1
autocommit TRUE autocommit TRUE
@ -1509,7 +1516,7 @@ net-read-timeout 30
net-retry-count 10 net-retry-count 10
net-write-timeout 60 net-write-timeout 60
old FALSE old FALSE
old-alter-table FALSE old-alter-table DEFAULT
old-mode old-mode
old-passwords FALSE old-passwords FALSE
old-style-user-limits FALSE old-style-user-limits FALSE

View File

@ -0,0 +1,33 @@
CREATE TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT AS (f2 * f2) VIRTUAL)engine=innodb;
INSERT INTO t1(f1, f2) VALUES(1, 1);
--echo #
--echo # ALGORITHM=$algorithm_type
--echo #
--enable_info
--echo # Add column at the end of the table
--error $error_code
--eval ALTER TABLE t1 ADD COLUMN f4 char(100) default "BIG WALL", ALGORITHM=$algorithm_type
--echo # Change virtual column expression
--error $error_code
--eval ALTER TABLE t1 CHANGE f3 f3 INT AS (f2 * f2) VIRTUAL, ALGORITHM=$algorithm_type
--echo # Add virtual column
--error $error_code
--eval ALTER TABLE t1 ADD COLUMN f5 INT AS (f2) VIRTUAL, ALGORITHM=$algorithm_type
--echo # Rename Column
--error $error_code
--eval ALTER TABLE t1 CHANGE f3 vcol INT AS (f2) VIRTUAL, ALGORITHM=$algorithm_type
--echo # Rename table
--error $error_code
--eval ALTER TABLE t1 RENAME t2, algorithm=$algorithm_type
DROP TABLE t2;
--disable_info

View File

@ -0,0 +1,33 @@
CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL,
f3 INT AS (f2 * f2) VIRTUAL,
f4 INT NOT NULL UNIQUE,
f5 INT NOT NULL,
INDEX`idx`(f2))ENGINE=INNODB;
CREATE TABLE t2(f1 INT NOT NULL, f2 INT NOT NULL,
INDEX(f1),
FOREIGN KEY `fidx` (f1) REFERENCES t1(f1))ENGINE=INNODB;
INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4);
SELECT @@alter_algorithm;
--enable_info
--error $error_code
--eval ALTER TABLE t1 ADD INDEX idx1(f4)
--error $error_code
--eval ALTER TABLE t1 DROP INDEX idx
--error $error_code
--eval ALTER TABLE t1 ADD UNIQUE INDEX u1(f2)
--error $error_code
--eval ALTER TABLE t1 DROP INDEX f4
SET foreign_key_checks = 0;
--error $error_code
--eval ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1)
DROP TABLE t2, t1;
--disable_info

View File

@ -0,0 +1,51 @@
CREATE TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT NULL,
f4 INT as (f2) STORED,
f5 INT as (f3) STORED,
PRIMARY KEY(f1))ROW_FORMAT=COMPRESSED, ENGINE=INNODB;
INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1);
SELECT @@alter_algorithm;
--enable_info
--echo # All the following cases needs table rebuild
--echo # Add and Drop primary key
--error $error_code
--eval ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1)
--echo # Make existing column NULLABLE
--error $error_code
--eval ALTER TABLE t1 MODIFY f2 INT
--echo # Make existing column NON-NULLABLE
--error $error_code
--eval ALTER TABLE t1 MODIFY f3 INT NOT NULL
--echo # Drop Stored Column
--error $error_code
--eval ALTER TABLE t1 DROP COLUMN f5
--echo # Add base non-generated column as a last column in the compressed table
--error $error_code
--eval ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL
--echo # Add base non-generated column but not in the last position
--error $error_code
--eval ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3
--echo # Force the table to rebuild
--error $error_code
--eval ALTER TABLE t1 FORCE
--echo # Row format changes
--error $error_code
--eval ALTER TABLE t1 ROW_FORMAT=COMPRESSED
--echo # Engine table
--error $error_code
--eval ALTER TABLE t1 ENGINE=INNODB
DROP TABLE t1;
--disable_info

View File

@ -0,0 +1,92 @@
--- alter_algorithm.result 2018-05-06 23:42:08.022302601 +0530
+++ alter_algorithm.reject 2018-05-06 23:42:16.382634082 +0530
@@ -7,35 +7,44 @@
INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1);
SELECT @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+COPY
# All the following cases needs table rebuild
# Add and Drop primary key
ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1);
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Make existing column NULLABLE
ALTER TABLE t1 MODIFY f2 INT;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Make existing column NON-NULLABLE
ALTER TABLE t1 MODIFY f3 INT NOT NULL;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Drop Stored Column
ALTER TABLE t1 DROP COLUMN f5;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Add base non-generated column as a last column in the compressed table
ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Add base non-generated column but not in the last position
ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Force the table to rebuild
ALTER TABLE t1 FORCE;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Row format changes
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Engine table
ALTER TABLE t1 ENGINE=INNODB;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
DROP TABLE t1;
affected rows: 0
CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL,
@@ -49,23 +58,23 @@
INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4);
SELECT @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+COPY
ALTER TABLE t1 ADD INDEX idx1(f4);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
ALTER TABLE t1 DROP INDEX idx;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
ALTER TABLE t1 ADD UNIQUE INDEX u1(f2);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
ALTER TABLE t1 DROP INDEX f4;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 0;
affected rows: 0
ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
DROP TABLE t2, t1;
affected rows: 0

View File

@ -0,0 +1,66 @@
--- alter_algorithm.result 2018-05-06 23:42:08.022302601 +0530
+++ alter_algorithm.reject 2018-05-06 23:45:23.813346814 +0530
@@ -7,35 +7,44 @@
INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1);
SELECT @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+INPLACE
# All the following cases needs table rebuild
# Add and Drop primary key
ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1);
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Make existing column NULLABLE
ALTER TABLE t1 MODIFY f2 INT;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Make existing column NON-NULLABLE
ALTER TABLE t1 MODIFY f3 INT NOT NULL;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Drop Stored Column
ALTER TABLE t1 DROP COLUMN f5;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Add base non-generated column as a last column in the compressed table
ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Add base non-generated column but not in the last position
ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Force the table to rebuild
ALTER TABLE t1 FORCE;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Row format changes
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
# Engine table
ALTER TABLE t1 ENGINE=INNODB;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t1;
affected rows: 0
CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL,
@@ -49,7 +58,7 @@
INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4);
SELECT @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+INPLACE
ALTER TABLE t1 ADD INDEX idx1(f4);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0

View File

@ -0,0 +1,78 @@
--- alter_algorithm.result 2018-05-06 23:42:08.022302601 +0530
+++ alter_algorithm.reject 2018-05-06 23:46:08.482772800 +0530
@@ -7,35 +7,35 @@
INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1);
SELECT @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+INSTANT
# All the following cases needs table rebuild
# Add and Drop primary key
ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1);
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Make existing column NULLABLE
ALTER TABLE t1 MODIFY f2 INT;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Make existing column NON-NULLABLE
ALTER TABLE t1 MODIFY f3 INT NOT NULL;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Drop Stored Column
ALTER TABLE t1 DROP COLUMN f5;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Add base non-generated column as a last column in the compressed table
ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Add base non-generated column but not in the last position
ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Force the table to rebuild
ALTER TABLE t1 FORCE;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Row format changes
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
# Engine table
ALTER TABLE t1 ENGINE=INNODB;
-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
+Got one of the listed errors
DROP TABLE t1;
affected rows: 0
CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL,
@@ -49,23 +49,18 @@
INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4);
SELECT @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+INSTANT
ALTER TABLE t1 ADD INDEX idx1(f4);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY
ALTER TABLE t1 DROP INDEX idx;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: DROP INDEX. Try ALGORITHM=NOCOPY
ALTER TABLE t1 ADD UNIQUE INDEX u1(f2);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY
ALTER TABLE t1 DROP INDEX f4;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: DROP INDEX. Try ALGORITHM=NOCOPY
SET foreign_key_checks = 0;
affected rows: 0
ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY
DROP TABLE t2, t1;
affected rows: 0

View File

@ -0,0 +1,71 @@
CREATE TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT NULL,
f4 INT as (f2) STORED,
f5 INT as (f3) STORED,
PRIMARY KEY(f1))ROW_FORMAT=COMPRESSED, ENGINE=INNODB;
INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1);
SELECT @@alter_algorithm;
@@alter_algorithm
NOCOPY
# All the following cases needs table rebuild
# Add and Drop primary key
ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1);
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Make existing column NULLABLE
ALTER TABLE t1 MODIFY f2 INT;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Make existing column NON-NULLABLE
ALTER TABLE t1 MODIFY f3 INT NOT NULL;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Drop Stored Column
ALTER TABLE t1 DROP COLUMN f5;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Add base non-generated column as a last column in the compressed table
ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Add base non-generated column but not in the last position
ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Force the table to rebuild
ALTER TABLE t1 FORCE;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Row format changes
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
# Engine table
ALTER TABLE t1 ENGINE=INNODB;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
DROP TABLE t1;
affected rows: 0
CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL,
f3 INT AS (f2 * f2) VIRTUAL,
f4 INT NOT NULL UNIQUE,
f5 INT NOT NULL,
INDEX`idx`(f2))ENGINE=INNODB;
CREATE TABLE t2(f1 INT NOT NULL, f2 INT NOT NULL,
INDEX(f1),
FOREIGN KEY `fidx` (f1) REFERENCES t1(f1))ENGINE=INNODB;
INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4);
SELECT @@alter_algorithm;
@@alter_algorithm
NOCOPY
ALTER TABLE t1 ADD INDEX idx1(f4);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE t1 DROP INDEX idx;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE t1 ADD UNIQUE INDEX u1(f2);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE t1 DROP INDEX f4;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 0;
affected rows: 0
ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t2, t1;
affected rows: 0

View File

@ -0,0 +1,61 @@
--- alter_instant.result 2018-04-10 11:19:46.299868465 +0530
+++ alter_instant.reject 2018-04-10 11:21:19.648918489 +0530
@@ -8,30 +8,30 @@
INSERT INTO t1(f1, f2) VALUES(1, 1);
select @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+COPY
# Add column at the end of the table
ALTER TABLE t1 ADD COLUMN f4 char(100) default "BIG WALL";
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Change virtual column expression
ALTER TABLE t1 CHANGE f3 f3 INT AS (f2 * f2) VIRTUAL;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Add virtual column
ALTER TABLE t1 ADD COLUMN f5 INT AS (f2) VIRTUAL;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Rename Column
ALTER TABLE t1 CHANGE f3 vcol INT AS (f2) VIRTUAL;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Rename table
ALTER TABLE t1 RENAME t3;
affected rows: 0
# Drop Virtual Column
ALTER TABLE t3 DROP COLUMN vcol;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
# Column length varies
ALTER TABLE t2 CHANGE f3 f3 VARCHAR(20);
affected rows: 0
@@ -39,12 +39,12 @@
SET foreign_key_checks = 0;
affected rows: 0
ALTER TABLE t3 ADD FOREIGN KEY `fidx`(f2) REFERENCES t2(f1);
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 1;
affected rows: 0
ALTER TABLE t3 DROP FOREIGN KEY `fidx`;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
DROP TABLE t3, t2;
affected rows: 0

View File

@ -0,0 +1,11 @@
--- alter_instant.result 2018-04-10 11:19:46.299868465 +0530
+++ alter_instant.reject 2018-04-10 11:22:19.433617807 +0530
@@ -8,7 +8,7 @@
INSERT INTO t1(f1, f2) VALUES(1, 1);
select @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+INPLACE
# Add column at the end of the table
ALTER TABLE t1 ADD COLUMN f4 char(100) default "BIG WALL";
affected rows: 0

View File

@ -0,0 +1,11 @@
--- alter_instant.result 2018-04-10 11:19:46.299868465 +0530
+++ alter_instant.reject 2018-04-10 11:22:47.281949905 +0530
@@ -8,7 +8,7 @@
INSERT INTO t1(f1, f2) VALUES(1, 1);
select @@alter_algorithm;
@@alter_algorithm
-NOCOPY
+INSTANT
# Add column at the end of the table
ALTER TABLE t1 ADD COLUMN f4 char(100) default "BIG WALL";
affected rows: 0

View File

@ -0,0 +1,50 @@
CREATE TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT AS (f2 * f2) VIRTUAL,
INDEX idx (f2))engine=innodb;
CREATE TABLE t2(f1 INT NOT NULL, f2 INT NOT NULL,
f3 VARCHAR(10),
INDEX(f1))ENGINE=INNODB;
INSERT INTO t1(f1, f2) VALUES(1, 1);
select @@alter_algorithm;
@@alter_algorithm
NOCOPY
# Add column at the end of the table
ALTER TABLE t1 ADD COLUMN f4 char(100) default "BIG WALL";
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
# Change virtual column expression
ALTER TABLE t1 CHANGE f3 f3 INT AS (f2 * f2) VIRTUAL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
# Add virtual column
ALTER TABLE t1 ADD COLUMN f5 INT AS (f2) VIRTUAL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
# Rename Column
ALTER TABLE t1 CHANGE f3 vcol INT AS (f2) VIRTUAL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
# Rename table
ALTER TABLE t1 RENAME t3;
affected rows: 0
# Drop Virtual Column
ALTER TABLE t3 DROP COLUMN vcol;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
# Column length varies
ALTER TABLE t2 CHANGE f3 f3 VARCHAR(20);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 0;
affected rows: 0
ALTER TABLE t3 ADD FOREIGN KEY `fidx`(f2) REFERENCES t2(f1);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 1;
affected rows: 0
ALTER TABLE t3 DROP FOREIGN KEY `fidx`;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t3, t2;
affected rows: 0

View File

@ -1,13 +1,13 @@
create table t1(a int not null primary key, b geometry not null) engine=innodb; create table t1(a int not null primary key, b geometry not null) engine=innodb;
ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b); ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b), ALGORITHM=INSTANT;
ERROR 0A000: LOCK=NONE is not supported. Reason: Do not support online operation on table with GIS index. Try LOCK=SHARED ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Do not support online operation on table with GIS index. Try ALGORITHM=NOCOPY
show warnings; show warnings;
Level Code Message Level Code Message
Error 1846 LOCK=NONE is not supported. Reason: Do not support online operation on table with GIS index. Try LOCK=SHARED Error 1846 ALGORITHM=INSTANT is not supported. Reason: Do not support online operation on table with GIS index. Try ALGORITHM=NOCOPY
show errors; show errors;
Level Code Message Level Code Message
Error 1846 LOCK=NONE is not supported. Reason: Do not support online operation on table with GIS index. Try LOCK=SHARED Error 1846 ALGORITHM=INSTANT is not supported. Reason: Do not support online operation on table with GIS index. Try ALGORITHM=NOCOPY
ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b), LOCK=SHARED; ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b), LOCK=SHARED, ALGORITHM=NOCOPY;
show warnings; show warnings;
Level Code Message Level Code Message
show errors; show errors;

View File

@ -36,14 +36,7 @@ SELECT COUNT(*)>0 FROM INFORMATION_SCHEMA.COLUMNS
LEFT JOIN t4 ON (NUMERIC_SCALE = pk); LEFT JOIN t4 ON (NUMERIC_SCALE = pk);
COUNT(*)>0 COUNT(*)>0
1 1
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL enter WAIT_FOR delete';
ALTER TABLE t4 ADD COLUMN c INT; ALTER TABLE t4 ADD COLUMN c INT;
connect dml,localhost,root,,;
SET DEBUG_SYNC='now WAIT_FOR enter';
DELETE FROM t4;
InnoDB 0 transactions not purged
SET DEBUG_SYNC='now SIGNAL delete';
connection default;
CREATE TABLE t5 (i INT, KEY(i)) ENGINE=InnoDB; CREATE TABLE t5 (i INT, KEY(i)) ENGINE=InnoDB;
INSERT INTO t5 VALUES (-42); INSERT INTO t5 VALUES (-42);
ALTER TABLE t5 ADD UNIQUE ui(i); ALTER TABLE t5 ADD UNIQUE ui(i);
@ -61,7 +54,7 @@ INSERT INTO t8 VALUES (NULL);
ALTER TABLE t8 ADD c CHAR(3); ALTER TABLE t8 ADD c CHAR(3);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL rebuilt WAIT_FOR dml'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL rebuilt WAIT_FOR dml';
ALTER TABLE t8 FORCE; ALTER TABLE t8 FORCE;
connection dml; connect dml,localhost,root,,;
SET DEBUG_SYNC='now WAIT_FOR rebuilt'; SET DEBUG_SYNC='now WAIT_FOR rebuilt';
BEGIN; BEGIN;
INSERT INTO t8 SET i=1; INSERT INTO t8 SET i=1;

View File

@ -0,0 +1,11 @@
[COPY]
--alter_algorithm=copy
[INPLACE]
--alter_algorithm=inplace
[NOCOPY]
--alter_algorithm=nocopy
[INSTANT]
--alter_algorithm=instant

View File

@ -0,0 +1,2 @@
# See also alter_algorithm.combinations
--source include/have_innodb.inc

View File

@ -0,0 +1,22 @@
--source include/have_innodb.inc
let $algorithm = `SELECT @@ALTER_ALGORITHM`;
let $error_code = 0;
if ($algorithm == "NOCOPY") {
let $error_code = ER_ALTER_OPERATION_NOT_SUPPORTED;
}
if ($algorithm == "INSTANT") {
let $error_code = ER_ALTER_OPERATION_NOT_SUPPORTED, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON;
}
--source include/alter_nocopy_fail.inc
if ($algorithm == "NOCOPY") {
let $error_code = 0;
}
if ($algorithm == "INSTANT") {
let $error_code = ER_ALTER_OPERATION_NOT_SUPPORTED_REASON;
}
--source include/alter_nocopy.inc

View File

@ -0,0 +1,45 @@
--source alter_algorithm.inc
CREATE TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT AS (f2 * f2) VIRTUAL,
INDEX idx (f2))engine=innodb;
CREATE TABLE t2(f1 INT NOT NULL, f2 INT NOT NULL,
f3 VARCHAR(10),
INDEX(f1))ENGINE=INNODB;
INSERT INTO t1(f1, f2) VALUES(1, 1);
select @@alter_algorithm;
--enable_info
--echo # Add column at the end of the table
--eval ALTER TABLE t1 ADD COLUMN f4 char(100) default "BIG WALL"
--echo # Change virtual column expression
--eval ALTER TABLE t1 CHANGE f3 f3 INT AS (f2 * f2) VIRTUAL
--echo # Add virtual column
--eval ALTER TABLE t1 ADD COLUMN f5 INT AS (f2) VIRTUAL
--echo # Rename Column
--eval ALTER TABLE t1 CHANGE f3 vcol INT AS (f2) VIRTUAL
--echo # Rename table
--eval ALTER TABLE t1 RENAME t3
--echo # Drop Virtual Column
--eval ALTER TABLE t3 DROP COLUMN vcol
--echo # Column length varies
--eval ALTER TABLE t2 CHANGE f3 f3 VARCHAR(20)
SET foreign_key_checks = 0;
--eval ALTER TABLE t3 ADD FOREIGN KEY `fidx`(f2) REFERENCES t2(f1)
SET foreign_key_checks = 1;
--eval ALTER TABLE t3 DROP FOREIGN KEY `fidx`
DROP TABLE t3, t2;
--disable_info

View File

@ -2,10 +2,10 @@
create table t1(a int not null primary key, b geometry not null) engine=innodb; create table t1(a int not null primary key, b geometry not null) engine=innodb;
--error 1846 --error 1846
ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b); ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b), ALGORITHM=INSTANT;
show warnings; show warnings;
show errors; show errors;
ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b), LOCK=SHARED; ALTER ONLINE TABLE t1 ADD SPATIAL INDEX new(b), LOCK=SHARED, ALGORITHM=NOCOPY;
show warnings; show warnings;
show errors; show errors;
drop table t1; drop table t1;

View File

@ -40,16 +40,7 @@ INSERT INTO t4 VALUES (0);
ALTER TABLE t4 ADD COLUMN b INT; ALTER TABLE t4 ADD COLUMN b INT;
SELECT COUNT(*)>0 FROM INFORMATION_SCHEMA.COLUMNS SELECT COUNT(*)>0 FROM INFORMATION_SCHEMA.COLUMNS
LEFT JOIN t4 ON (NUMERIC_SCALE = pk); LEFT JOIN t4 ON (NUMERIC_SCALE = pk);
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL enter WAIT_FOR delete';
--send
ALTER TABLE t4 ADD COLUMN c INT; ALTER TABLE t4 ADD COLUMN c INT;
connect (dml,localhost,root,,);
SET DEBUG_SYNC='now WAIT_FOR enter';
DELETE FROM t4;
--source include/wait_all_purged.inc
SET DEBUG_SYNC='now SIGNAL delete';
connection default;
reap;
CREATE TABLE t5 (i INT, KEY(i)) ENGINE=InnoDB; CREATE TABLE t5 (i INT, KEY(i)) ENGINE=InnoDB;
INSERT INTO t5 VALUES (-42); INSERT INTO t5 VALUES (-42);
@ -72,7 +63,7 @@ ALTER TABLE t8 ADD c CHAR(3);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL rebuilt WAIT_FOR dml'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL rebuilt WAIT_FOR dml';
--send --send
ALTER TABLE t8 FORCE; ALTER TABLE t8 FORCE;
connection dml; connect (dml,localhost,root,,);
SET DEBUG_SYNC='now WAIT_FOR rebuilt'; SET DEBUG_SYNC='now WAIT_FOR rebuilt';
BEGIN; BEGIN;
INSERT INTO t8 SET i=1; INSERT INTO t8 SET i=1;

View File

@ -10,7 +10,9 @@ INSERT INTO fts_test (title,body) VALUES
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...'); ('MySQL Security','When configured properly, MySQL ...');
CREATE FULLTEXT INDEX idx on fts_test (title, body); ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE
ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=INPLACE;
Warnings: Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SELECT * FROM fts_test WHERE MATCH (title, body) SELECT * FROM fts_test WHERE MATCH (title, body)
@ -26,7 +28,7 @@ INSERT INTO fts_test (title,body) VALUES
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...'); ('MySQL Security','When configured properly, MySQL ...');
CREATE FULLTEXT INDEX idx on fts_test (title, body); ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
SELECT * FROM fts_test WHERE MATCH (title, body) SELECT * FROM fts_test WHERE MATCH (title, body)
AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE);
id title body id title body
@ -68,7 +70,6 @@ FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200), title VARCHAR(200),
body TEXT body TEXT
) ENGINE=InnoDB; ) ENGINE=InnoDB;
create unique index FTS_DOC_ID_INDEX on fts_test(FTS_DOC_ID);
INSERT INTO fts_test (title,body) VALUES INSERT INTO fts_test (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...') , ('MySQL Tutorial','DBMS stands for DataBase ...') ,
('How To Use MySQL Well','After you went through a ...'), ('How To Use MySQL Well','After you went through a ...'),
@ -78,7 +79,7 @@ INSERT INTO fts_test (title,body) VALUES
('MySQL Security','When configured properly, MySQL ...'); ('MySQL Security','When configured properly, MySQL ...');
CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE; CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE;
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
CREATE FULLTEXT INDEX idx on fts_test (title, body); ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE; ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE;
ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED
ALTER TABLE fts_test ROW_FORMAT=REDUNDANT; ALTER TABLE fts_test ROW_FORMAT=REDUNDANT;
@ -95,7 +96,6 @@ FTS_DOC_ID title body
1 MySQL Tutorial DBMS stands for DataBase ... 1 MySQL Tutorial DBMS stands for DataBase ...
3 Optimizing MySQL In this tutorial we will show ... 3 Optimizing MySQL In this tutorial we will show ...
drop index idx on fts_test; drop index idx on fts_test;
drop index FTS_DOC_ID_INDEX on fts_test;
CREATE FULLTEXT INDEX idx on fts_test (title, body); CREATE FULLTEXT INDEX idx on fts_test (title, body);
SELECT * FROM fts_test WHERE MATCH (title, body) SELECT * FROM fts_test WHERE MATCH (title, body)
AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE);
@ -202,7 +202,7 @@ FTS_DOC_ID title body
DROP TABLE articles; DROP TABLE articles;
create table articles(`FTS_DOC_ID` serial, create table articles(`FTS_DOC_ID` serial,
`col32` timestamp not null,`col115` text) engine=innodb; `col32` timestamp not null,`col115` text) engine=innodb;
create fulltext index `idx5` on articles(`col115`) ; create fulltext index `idx5` on articles(`col115`) ;
alter ignore table articles add primary key (`col32`) ; alter ignore table articles add primary key (`col32`) ;
drop table articles; drop table articles;
CREATE TABLE articles ( CREATE TABLE articles (

View File

@ -18,14 +18,17 @@ INSERT INTO fts_test (title,body) VALUES
('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...'); ('MySQL Security','When configured properly, MySQL ...');
# Table does rebuild when fts index builds for the first time
--error ER_ALTER_OPERATION_NOT_SUPPORTED
ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
# Create the FTS index # Create the FTS index
CREATE FULLTEXT INDEX idx on fts_test (title, body); ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=INPLACE;
# Select word "tutorial" in the table # Select word "tutorial" in the table
SELECT * FROM fts_test WHERE MATCH (title, body) SELECT * FROM fts_test WHERE MATCH (title, body)
AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE);
# Drop the FTS idx # Drop the FTS idx
DROP INDEX idx ON fts_test; DROP INDEX idx ON fts_test;
@ -38,9 +41,8 @@ INSERT INTO fts_test (title,body) VALUES
('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...'); ('MySQL Security','When configured properly, MySQL ...');
# FTS_DOC_ID hidden column and FTS_DOC_ID index exist
# Recreate the FTS index ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
CREATE FULLTEXT INDEX idx on fts_test (title, body);
# Select word "tutorial" in the table # Select word "tutorial" in the table
SELECT * FROM fts_test WHERE MATCH (title, body) SELECT * FROM fts_test WHERE MATCH (title, body)
@ -81,8 +83,6 @@ CREATE TABLE fts_test (
body TEXT body TEXT
) ENGINE=InnoDB; ) ENGINE=InnoDB;
create unique index FTS_DOC_ID_INDEX on fts_test(FTS_DOC_ID);
# Insert six rows # Insert six rows
INSERT INTO fts_test (title,body) VALUES INSERT INTO fts_test (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...') , ('MySQL Tutorial','DBMS stands for DataBase ...') ,
@ -97,7 +97,7 @@ INSERT INTO fts_test (title,body) VALUES
# column already exists. This has not been implemented yet. # column already exists. This has not been implemented yet.
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE; CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE;
CREATE FULLTEXT INDEX idx on fts_test (title, body); ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE; ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE;
@ -117,8 +117,6 @@ SELECT * FROM fts_test WHERE MATCH (title, body)
# Drop the FTS_DOC_ID_INDEX and try again # Drop the FTS_DOC_ID_INDEX and try again
drop index idx on fts_test; drop index idx on fts_test;
drop index FTS_DOC_ID_INDEX on fts_test;
CREATE FULLTEXT INDEX idx on fts_test (title, body); CREATE FULLTEXT INDEX idx on fts_test (title, body);
SELECT * FROM fts_test WHERE MATCH (title, body) SELECT * FROM fts_test WHERE MATCH (title, body)
@ -232,7 +230,7 @@ DROP TABLE articles;
create table articles(`FTS_DOC_ID` serial, create table articles(`FTS_DOC_ID` serial,
`col32` timestamp not null,`col115` text) engine=innodb; `col32` timestamp not null,`col115` text) engine=innodb;
create fulltext index `idx5` on articles(`col115`) ; create fulltext index `idx5` on articles(`col115`) ;
alter ignore table articles add primary key (`col32`) ; alter ignore table articles add primary key (`col32`) ;

View File

@ -1,45 +1,105 @@
SET @start_global_value = @@global.old_alter_table; SET @start_global_value = @@global.old_alter_table;
SELECT @start_global_value; SELECT @start_global_value;
@start_global_value @start_global_value
0 DEFAULT
select @@global.old_alter_table; select @@global.old_alter_table;
@@global.old_alter_table @@global.old_alter_table
0 DEFAULT
select @@session.old_alter_table; select @@session.old_alter_table;
@@session.old_alter_table @@session.old_alter_table
0 DEFAULT
show global variables like 'old_alter_table'; show global variables like 'old_alter_table';
Variable_name Value Variable_name Value
old_alter_table OFF old_alter_table DEFAULT
show session variables like 'old_alter_table'; show session variables like 'old_alter_table';
Variable_name Value Variable_name Value
old_alter_table OFF old_alter_table DEFAULT
select * from information_schema.global_variables where variable_name='old_alter_table'; select * from information_schema.global_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE OFF OLD_ALTER_TABLE DEFAULT
select * from information_schema.session_variables where variable_name='old_alter_table'; select * from information_schema.session_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE OFF OLD_ALTER_TABLE DEFAULT
set global old_alter_table=1; set global old_alter_table=1;
set session old_alter_table=ON; set session old_alter_table=1;
select @@global.old_alter_table; select @@global.old_alter_table;
@@global.old_alter_table @@global.old_alter_table
1 COPY
select @@session.old_alter_table; select @@session.old_alter_table;
@@session.old_alter_table @@session.old_alter_table
1 COPY
show global variables like 'old_alter_table'; show global variables like 'old_alter_table';
Variable_name Value Variable_name Value
old_alter_table ON old_alter_table COPY
show session variables like 'old_alter_table'; show session variables like 'old_alter_table';
Variable_name Value Variable_name Value
old_alter_table ON old_alter_table COPY
select * from information_schema.global_variables where variable_name='old_alter_table'; select * from information_schema.global_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE ON OLD_ALTER_TABLE COPY
select * from information_schema.session_variables where variable_name='old_alter_table'; select * from information_schema.session_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE ON OLD_ALTER_TABLE COPY
set global old_alter_table=2;
set session old_alter_table=2;
select @@global.old_alter_table;
@@global.old_alter_table
INPLACE
select @@session.old_alter_table;
@@session.old_alter_table
INPLACE
show global variables like 'old_alter_table';
Variable_name Value
old_alter_table INPLACE
show session variables like 'old_alter_table';
Variable_name Value
old_alter_table INPLACE
select * from information_schema.global_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE INPLACE
select * from information_schema.session_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE INPLACE
set global old_alter_table=3;
set session old_alter_table=3;
select @@global.old_alter_table;
@@global.old_alter_table
NOCOPY
select @@session.old_alter_table;
@@session.old_alter_table
NOCOPY
show global variables like 'old_alter_table';
Variable_name Value
old_alter_table NOCOPY
show session variables like 'old_alter_table';
Variable_name Value
old_alter_table NOCOPY
select * from information_schema.global_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE NOCOPY
select * from information_schema.session_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE NOCOPY
set global old_alter_table=4;
set session old_alter_table=4;
select @@global.old_alter_table;
@@global.old_alter_table
INSTANT
select @@session.old_alter_table;
@@session.old_alter_table
INSTANT
show global variables like 'old_alter_table';
Variable_name Value
old_alter_table INSTANT
show session variables like 'old_alter_table';
Variable_name Value
old_alter_table INSTANT
select * from information_schema.global_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE INSTANT
select * from information_schema.session_variables where variable_name='old_alter_table';
VARIABLE_NAME VARIABLE_VALUE
OLD_ALTER_TABLE INSTANT
set global old_alter_table=1.1; set global old_alter_table=1.1;
ERROR 42000: Incorrect argument type to variable 'old_alter_table' ERROR 42000: Incorrect argument type to variable 'old_alter_table'
set global old_alter_table=1e1; set global old_alter_table=1e1;
@ -49,4 +109,4 @@ ERROR 42000: Variable 'old_alter_table' can't be set to the value of 'foo'
SET @@global.old_alter_table = @start_global_value; SET @@global.old_alter_table = @start_global_value;
SELECT @@global.old_alter_table; SELECT @@global.old_alter_table;
@@global.old_alter_table @@global.old_alter_table
0 DEFAULT

View File

@ -26,6 +26,20 @@ variable_name not in (
'version_malloc_library', 'version_ssl_library', 'version' 'version_malloc_library', 'version_ssl_library', 'version'
) )
order by variable_name; order by variable_name;
VARIABLE_NAME ALTER_ALGORITHM
SESSION_VALUE DEFAULT
GLOBAL_VALUE DEFAULT
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE DEFAULT
VARIABLE_SCOPE SESSION
VARIABLE_TYPE ENUM
VARIABLE_COMMENT Specify the alter table algorithm
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST DEFAULT,COPY,INPLACE,NOCOPY,INSTANT
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME AUTOCOMMIT VARIABLE_NAME AUTOCOMMIT
SESSION_VALUE ON SESSION_VALUE ON
GLOBAL_VALUE ON GLOBAL_VALUE ON
@ -2589,17 +2603,17 @@ ENUM_VALUE_LIST OFF,ON
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME OLD_ALTER_TABLE VARIABLE_NAME OLD_ALTER_TABLE
SESSION_VALUE OFF SESSION_VALUE DEFAULT
GLOBAL_VALUE OFF GLOBAL_VALUE DEFAULT
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF DEFAULT_VALUE DEFAULT
VARIABLE_SCOPE SESSION VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN VARIABLE_TYPE ENUM
VARIABLE_COMMENT Use old, non-optimized alter table VARIABLE_COMMENT Alias for alter_algorithm. Deprecated. Use --alter-algorithm instead.
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON ENUM_VALUE_LIST DEFAULT,COPY,INPLACE,NOCOPY,INSTANT
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME OLD_MODE VARIABLE_NAME OLD_MODE

View File

@ -26,6 +26,20 @@ variable_name not in (
'version_malloc_library', 'version_ssl_library', 'version' 'version_malloc_library', 'version_ssl_library', 'version'
) )
order by variable_name; order by variable_name;
VARIABLE_NAME ALTER_ALGORITHM
SESSION_VALUE DEFAULT
GLOBAL_VALUE DEFAULT
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE DEFAULT
VARIABLE_SCOPE SESSION
VARIABLE_TYPE ENUM
VARIABLE_COMMENT Specify the alter table algorithm
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST DEFAULT,COPY,INPLACE,NOCOPY,INSTANT
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME AUTOCOMMIT VARIABLE_NAME AUTOCOMMIT
SESSION_VALUE ON SESSION_VALUE ON
GLOBAL_VALUE ON GLOBAL_VALUE ON
@ -2799,17 +2813,17 @@ ENUM_VALUE_LIST OFF,ON
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME OLD_ALTER_TABLE VARIABLE_NAME OLD_ALTER_TABLE
SESSION_VALUE OFF SESSION_VALUE DEFAULT
GLOBAL_VALUE OFF GLOBAL_VALUE DEFAULT
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF DEFAULT_VALUE DEFAULT
VARIABLE_SCOPE SESSION VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN VARIABLE_TYPE ENUM
VARIABLE_COMMENT Use old, non-optimized alter table VARIABLE_COMMENT Alias for alter_algorithm. Deprecated. Use --alter-algorithm instead.
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON ENUM_VALUE_LIST DEFAULT,COPY,INPLACE,NOCOPY,INSTANT
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME OLD_MODE VARIABLE_NAME OLD_MODE

View File

@ -20,7 +20,7 @@ select * from information_schema.session_variables where variable_name='old_alte
# show that it's writable # show that it's writable
# #
set global old_alter_table=1; set global old_alter_table=1;
set session old_alter_table=ON; set session old_alter_table=1;
select @@global.old_alter_table; select @@global.old_alter_table;
select @@session.old_alter_table; select @@session.old_alter_table;
show global variables like 'old_alter_table'; show global variables like 'old_alter_table';
@ -28,6 +28,32 @@ show session variables like 'old_alter_table';
select * from information_schema.global_variables where variable_name='old_alter_table'; select * from information_schema.global_variables where variable_name='old_alter_table';
select * from information_schema.session_variables where variable_name='old_alter_table'; select * from information_schema.session_variables where variable_name='old_alter_table';
set global old_alter_table=2;
set session old_alter_table=2;
select @@global.old_alter_table;
select @@session.old_alter_table;
show global variables like 'old_alter_table';
show session variables like 'old_alter_table';
select * from information_schema.global_variables where variable_name='old_alter_table';
select * from information_schema.session_variables where variable_name='old_alter_table';
set global old_alter_table=3;
set session old_alter_table=3;
select @@global.old_alter_table;
select @@session.old_alter_table;
show global variables like 'old_alter_table';
show session variables like 'old_alter_table';
select * from information_schema.global_variables where variable_name='old_alter_table';
select * from information_schema.session_variables where variable_name='old_alter_table';
set global old_alter_table=4;
set session old_alter_table=4;
select @@global.old_alter_table;
select @@session.old_alter_table;
show global variables like 'old_alter_table';
show session variables like 'old_alter_table';
select * from information_schema.global_variables where variable_name='old_alter_table';
select * from information_schema.session_variables where variable_name='old_alter_table';
# #
# incorrect types # incorrect types
# #

View File

@ -454,8 +454,6 @@ t CREATE TABLE `t` (
`c` text DEFAULT NULL `c` text DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING ) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
alter table t add fulltext key (c); alter table t add fulltext key (c);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
create or replace table t (a int) with system versioning; create or replace table t (a int) with system versioning;
alter table t drop column a; alter table t drop column a;
ERROR HY000: Table `t` must have at least one versioned column ERROR HY000: Table `t` must have at least one versioned column

View File

@ -4471,7 +4471,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
} }
void Alter_inplace_info::report_unsupported_error(const char *not_supported, void Alter_inplace_info::report_unsupported_error(const char *not_supported,
const char *try_instead) const char *try_instead) const
{ {
if (unsupported_reason == NULL) if (unsupported_reason == NULL)
my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),

View File

@ -73,11 +73,14 @@ class sequence_definition;
*/ */
enum enum_alter_inplace_result { enum enum_alter_inplace_result {
HA_ALTER_ERROR, HA_ALTER_ERROR,
HA_ALTER_INPLACE_COPY_NO_LOCK,
HA_ALTER_INPLACE_COPY_LOCK,
HA_ALTER_INPLACE_NOCOPY_LOCK,
HA_ALTER_INPLACE_NOCOPY_NO_LOCK,
HA_ALTER_INPLACE_INSTANT,
HA_ALTER_INPLACE_NOT_SUPPORTED, HA_ALTER_INPLACE_NOT_SUPPORTED,
HA_ALTER_INPLACE_EXCLUSIVE_LOCK, HA_ALTER_INPLACE_EXCLUSIVE_LOCK,
HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE,
HA_ALTER_INPLACE_SHARED_LOCK, HA_ALTER_INPLACE_SHARED_LOCK,
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE,
HA_ALTER_INPLACE_NO_LOCK HA_ALTER_INPLACE_NO_LOCK
}; };
@ -2304,8 +2307,7 @@ public:
/** /**
Can be set by handler to describe why a given operation cannot be done Can be set by handler to describe why a given operation cannot be done
in-place (HA_ALTER_INPLACE_NOT_SUPPORTED) or why it cannot be done in-place (HA_ALTER_INPLACE_NOT_SUPPORTED) or why it cannot be done
online (HA_ALTER_INPLACE_NO_LOCK or online (HA_ALTER_INPLACE_NO_LOCK or HA_ALTER_INPLACE_COPY_NO_LOCK)
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE)
If set, it will be used with ER_ALTER_OPERATION_NOT_SUPPORTED_REASON if If set, it will be used with ER_ALTER_OPERATION_NOT_SUPPORTED_REASON if
results from handler::check_if_supported_inplace_alter() doesn't match results from handler::check_if_supported_inplace_alter() doesn't match
requirements set by user. If not set, the more generic requirements set by user. If not set, the more generic
@ -2353,7 +2355,7 @@ public:
replace not_supported with. replace not_supported with.
*/ */
void report_unsupported_error(const char *not_supported, void report_unsupported_error(const char *not_supported,
const char *try_instead); const char *try_instead) const;
}; };
@ -4060,8 +4062,8 @@ public:
*) As the first step, we acquire a lock corresponding to the concurrency *) As the first step, we acquire a lock corresponding to the concurrency
level which was returned by handler::check_if_supported_inplace_alter() level which was returned by handler::check_if_supported_inplace_alter()
and requested by the user. This lock is held for most of the and requested by the user. This lock is held for most of the
duration of in-place ALTER (if HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE duration of in-place ALTER (if HA_ALTER_INPLACE_COPY_LOCK
or HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE were returned we acquire an or HA_ALTER_INPLACE_COPY_NO_LOCK were returned we acquire an
exclusive lock for duration of the next step only). exclusive lock for duration of the next step only).
*) After that we call handler::ha_prepare_inplace_alter_table() to give the *) After that we call handler::ha_prepare_inplace_alter_table() to give the
storage engine a chance to update its internal structures with a higher storage engine a chance to update its internal structures with a higher
@ -4105,12 +4107,12 @@ public:
@retval HA_ALTER_ERROR Unexpected error. @retval HA_ALTER_ERROR Unexpected error.
@retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy. @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy.
@retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock. @retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock.
@retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE @retval HA_ALTER_INPLACE_COPY_LOCK
Supported, but requires SNW lock Supported, but requires SNW lock
during main phase. Prepare phase during main phase. Prepare phase
requires X lock. requires X lock.
@retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock. @retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock.
@retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE @retval HA_ALTER_INPLACE_COPY_NO_LOCK
Supported, concurrent reads/writes Supported, concurrent reads/writes
allowed. However, prepare phase allowed. However, prepare phase
requires X lock. requires X lock.
@ -4170,10 +4172,9 @@ protected:
/** /**
Allows the storage engine to update internal structures with concurrent Allows the storage engine to update internal structures with concurrent
writes blocked. If check_if_supported_inplace_alter() returns writes blocked. If check_if_supported_inplace_alter() returns
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE or HA_ALTER_INPLACE_COPY_NO_LOCK or HA_ALTER_INPLACE_COPY_LOCK,
HA_ALTER_INPLACE_SHARED_AFTER_PREPARE, this function is called with this function is called with exclusive lock otherwise the same level
exclusive lock otherwise the same level of locking as for of locking as for inplace_alter_table() will be used.
inplace_alter_table() will be used.
@note Storage engines are responsible for reporting any errors by @note Storage engines are responsible for reporting any errors by
calling my_error()/print_error() calling my_error()/print_error()

View File

@ -1036,6 +1036,8 @@ handle_rpl_parallel_thread(void *arg)
thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
thd->security_ctx->skip_grants(); thd->security_ctx->skip_grants();
thd->variables.max_allowed_packet= slave_max_allowed_packet; thd->variables.max_allowed_packet= slave_max_allowed_packet;
/* Ensure that slave can exeute any alter table it gets from master */
thd->variables.alter_algorithm= (ulong) Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT;
thd->slave_thread= 1; thd->slave_thread= 1;
set_slave_thread_options(thd); set_slave_thread_options(thd);

View File

@ -5278,6 +5278,10 @@ pthread_handler_t handle_slave_sql(void *arg)
applied. In all other cases it must be FALSE. applied. In all other cases it must be FALSE.
*/ */
thd->variables.binlog_annotate_row_events= 0; thd->variables.binlog_annotate_row_events= 0;
/* Ensure that slave can exeute any alter table it gets from master */
thd->variables.alter_algorithm= (ulong) Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT;
add_to_active_threads(thd); add_to_active_threads(thd);
/* /*
We are going to set slave_running to 1. Assuming slave I/O thread is We are going to set slave_running to 1. Assuming slave I/O thread is

View File

@ -60,6 +60,10 @@ bool Alter_info::set_requested_algorithm(const LEX_CSTRING *str)
requested_algorithm= ALTER_TABLE_ALGORITHM_COPY; requested_algorithm= ALTER_TABLE_ALGORITHM_COPY;
else if (lex_string_eq(str, STRING_WITH_LEN("DEFAULT"))) else if (lex_string_eq(str, STRING_WITH_LEN("DEFAULT")))
requested_algorithm= ALTER_TABLE_ALGORITHM_DEFAULT; requested_algorithm= ALTER_TABLE_ALGORITHM_DEFAULT;
else if (lex_string_eq(str, STRING_WITH_LEN("NOCOPY")))
requested_algorithm= ALTER_TABLE_ALGORITHM_NOCOPY;
else if (lex_string_eq(str, STRING_WITH_LEN("INSTANT")))
requested_algorithm= ALTER_TABLE_ALGORITHM_INSTANT;
else else
return true; return true;
return false; return false;
@ -82,6 +86,128 @@ bool Alter_info::set_requested_lock(const LEX_CSTRING *str)
return false; return false;
} }
const char* Alter_info::algorithm() const
{
switch (requested_algorithm) {
case ALTER_TABLE_ALGORITHM_INPLACE:
return "ALGORITHM=INPLACE";
case ALTER_TABLE_ALGORITHM_COPY:
return "ALGORITHM=COPY";
case ALTER_TABLE_ALGORITHM_DEFAULT:
return "ALGORITHM=DEFAULT";
case ALTER_TABLE_ALGORITHM_NOCOPY:
return "ALGORITHM=NOCOPY";
case ALTER_TABLE_ALGORITHM_INSTANT:
return "ALGORITHM=INSTANT";
}
return NULL; /* purecov: begin deadcode */
}
const char* Alter_info::lock() const
{
switch (requested_lock) {
case ALTER_TABLE_LOCK_SHARED:
return "LOCK=SHARED";
case ALTER_TABLE_LOCK_NONE:
return "LOCK=NONE";
case ALTER_TABLE_LOCK_DEFAULT:
return "LOCK=DEFAULT";
case ALTER_TABLE_LOCK_EXCLUSIVE:
return "LOCK=EXCLUSIVE";
}
return NULL; /* purecov: begin deadcode */
}
bool Alter_info::supports_algorithm(THD *thd, enum_alter_inplace_result result,
const Alter_inplace_info *ha_alter_info)
{
if (requested_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
requested_algorithm = (Alter_info::enum_alter_table_algorithm) thd->variables.alter_algorithm;
switch (result) {
case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
case HA_ALTER_INPLACE_SHARED_LOCK:
case HA_ALTER_INPLACE_NO_LOCK:
case HA_ALTER_INPLACE_INSTANT:
return false;
case HA_ALTER_INPLACE_COPY_NO_LOCK:
case HA_ALTER_INPLACE_COPY_LOCK:
if (requested_algorithm >= Alter_info::ALTER_TABLE_ALGORITHM_NOCOPY)
{
ha_alter_info->report_unsupported_error(algorithm(),
"ALGORITHM=INPLACE");
return true;
}
return false;
case HA_ALTER_INPLACE_NOCOPY_NO_LOCK:
case HA_ALTER_INPLACE_NOCOPY_LOCK:
if (requested_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_INSTANT)
{
ha_alter_info->report_unsupported_error("ALGORITHM=INSTANT",
"ALGORITHM=NOCOPY");
return true;
}
return false;
case HA_ALTER_INPLACE_NOT_SUPPORTED:
if (requested_algorithm >= Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
{
ha_alter_info->report_unsupported_error(algorithm(),
"ALGORITHM=COPY");
return true;
}
return false;
case HA_ALTER_ERROR:
return true;
}
/* purecov: begin deadcode */
DBUG_ASSERT(0);
return false;
}
bool Alter_info::supports_lock(THD *thd, enum_alter_inplace_result result,
const Alter_inplace_info *ha_alter_info)
{
switch (result) {
case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
// If SHARED lock and no particular algorithm was requested, use COPY.
if (requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED &&
requested_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT &&
thd->variables.alter_algorithm ==
Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
return false;
if (requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED ||
requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
{
ha_alter_info->report_unsupported_error(lock(), "LOCK=EXCLUSIVE");
return true;
}
return false;
case HA_ALTER_INPLACE_NO_LOCK:
case HA_ALTER_INPLACE_INSTANT:
case HA_ALTER_INPLACE_COPY_NO_LOCK:
case HA_ALTER_INPLACE_NOCOPY_NO_LOCK:
return false;
case HA_ALTER_INPLACE_COPY_LOCK:
case HA_ALTER_INPLACE_NOCOPY_LOCK:
case HA_ALTER_INPLACE_NOT_SUPPORTED:
case HA_ALTER_INPLACE_SHARED_LOCK:
if (requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
{
ha_alter_info->report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
return true;
}
return false;
case HA_ALTER_ERROR:
return true;
}
/* purecov: begin deadcode */
DBUG_ASSERT(0);
return false;
}
Alter_table_ctx::Alter_table_ctx() Alter_table_ctx::Alter_table_ctx()
: datetime_field(NULL), error_if_not_empty(false), : datetime_field(NULL), error_if_not_empty(false),

View File

@ -47,14 +47,24 @@ public:
*/ */
enum enum_alter_table_algorithm enum enum_alter_table_algorithm
{ {
// In-place if supported, copy otherwise. /*
Use thd->variables.alter_algorithm for alter method. If this is also
default then use the fastest possible ALTER TABLE method
(INSTANT, NOCOPY, INPLACE, COPY)
*/
ALTER_TABLE_ALGORITHM_DEFAULT, ALTER_TABLE_ALGORITHM_DEFAULT,
// Copy if supported, error otherwise.
ALTER_TABLE_ALGORITHM_COPY,
// In-place if supported, error otherwise. // In-place if supported, error otherwise.
ALTER_TABLE_ALGORITHM_INPLACE, ALTER_TABLE_ALGORITHM_INPLACE,
// Copy if supported, error otherwise. // No Copy will refuse any operation which does rebuild.
ALTER_TABLE_ALGORITHM_COPY ALTER_TABLE_ALGORITHM_NOCOPY,
// Instant should allow any operation that changes metadata only.
ALTER_TABLE_ALGORITHM_INSTANT
}; };
@ -67,7 +77,7 @@ public:
// Maximum supported level of concurency for the given operation. // Maximum supported level of concurency for the given operation.
ALTER_TABLE_LOCK_DEFAULT, ALTER_TABLE_LOCK_DEFAULT,
// Allow concurrent reads & writes. If not supported, give erorr. // Allow concurrent reads & writes. If not supported, give error.
ALTER_TABLE_LOCK_NONE, ALTER_TABLE_LOCK_NONE,
// Allow concurrent reads only. If not supported, give error. // Allow concurrent reads only. If not supported, give error.
@ -174,6 +184,45 @@ public:
bool set_requested_lock(const LEX_CSTRING *str); bool set_requested_lock(const LEX_CSTRING *str);
/**
Returns the algorithm value in the format "algorithm=value"
*/
const char* algorithm() const;
/**
Returns the lock value in the format "lock=value"
*/
const char* lock() const;
/**
Check whether the given result can be supported
with the specified user alter algorithm.
@param thd Thread handle
@param result Operation supported for inplace alter
@param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data during
in-place alter
@retval false Supported operation
@retval true Not supported value
*/
bool supports_algorithm(THD *thd, enum_alter_inplace_result result,
const Alter_inplace_info *ha_alter_info);
/**
Check whether the given result can be supported
with the specified user lock type.
@param result Operation supported for inplace alter
@param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data during
in-place alter
@retval false Supported lock type
@retval true Not supported value
*/
bool supports_lock(THD *thd, enum_alter_inplace_result result,
const Alter_inplace_info *ha_alter_info);
private: private:
Alter_info &operator=(const Alter_info &rhs); // not implemented Alter_info &operator=(const Alter_info &rhs); // not implemented
Alter_info(const Alter_info &rhs); // not implemented Alter_info(const Alter_info &rhs); // not implemented

View File

@ -632,6 +632,7 @@ typedef struct system_variables
ulong query_cache_type; ulong query_cache_type;
ulong tx_isolation; ulong tx_isolation;
ulong updatable_views_with_limit; ulong updatable_views_with_limit;
ulong alter_algorithm;
int max_user_connections; int max_user_connections;
ulong server_id; ulong server_id;
/** /**
@ -655,7 +656,6 @@ typedef struct system_variables
my_bool keep_files_on_create; my_bool keep_files_on_create;
my_bool old_mode; my_bool old_mode;
my_bool old_alter_table;
my_bool old_passwords; my_bool old_passwords;
my_bool big_tables; my_bool big_tables;
my_bool only_standard_compliant_cte; my_bool only_standard_compliant_cte;

View File

@ -7370,8 +7370,11 @@ static bool mysql_inplace_alter_table(THD *thd,
exclusive lock is required for duration of the whole statement. exclusive lock is required for duration of the whole statement.
*/ */
if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK || if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE || ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) && inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
(thd->locked_tables_mode == LTM_LOCK_TABLES || (thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) || thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE) alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
@ -7395,8 +7398,11 @@ static bool mysql_inplace_alter_table(THD *thd,
*/ */
reopen_tables= true; reopen_tables= true;
} }
else if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE || else if (inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_INSTANT)
{ {
/* /*
Storage engine has requested exclusive lock only for prepare phase Storage engine has requested exclusive lock only for prepare phase
@ -7441,7 +7447,9 @@ static bool mysql_inplace_alter_table(THD *thd,
DBUG_ASSERT(0); DBUG_ASSERT(0);
// fall through // fall through
case HA_ALTER_INPLACE_NO_LOCK: case HA_ALTER_INPLACE_NO_LOCK:
case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE: case HA_ALTER_INPLACE_INSTANT:
case HA_ALTER_INPLACE_COPY_NO_LOCK:
case HA_ALTER_INPLACE_NOCOPY_NO_LOCK:
switch (alter_info->requested_lock) { switch (alter_info->requested_lock) {
case Alter_info::ALTER_TABLE_LOCK_DEFAULT: case Alter_info::ALTER_TABLE_LOCK_DEFAULT:
case Alter_info::ALTER_TABLE_LOCK_NONE: case Alter_info::ALTER_TABLE_LOCK_NONE:
@ -7453,8 +7461,9 @@ static bool mysql_inplace_alter_table(THD *thd,
} }
break; break;
case HA_ALTER_INPLACE_EXCLUSIVE_LOCK: case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
case HA_ALTER_INPLACE_SHARED_LOCK: case HA_ALTER_INPLACE_SHARED_LOCK:
case HA_ALTER_INPLACE_COPY_LOCK:
case HA_ALTER_INPLACE_NOCOPY_LOCK:
break; break;
} }
@ -7469,19 +7478,23 @@ static bool mysql_inplace_alter_table(THD *thd,
necessary only for prepare phase (unless we are not under LOCK TABLES) and necessary only for prepare phase (unless we are not under LOCK TABLES) and
user has not explicitly requested exclusive lock. user has not explicitly requested exclusive lock.
*/ */
if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE || if ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) && inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK) &&
!(thd->locked_tables_mode == LTM_LOCK_TABLES || !(thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) && thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
(alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)) (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
{ {
/* If storage engine or user requested shared lock downgrade to SNW. */ /* If storage engine or user requested shared lock downgrade to SNW. */
if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE || if (inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED) alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED)
table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_WRITE); table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_WRITE);
else else
{ {
DBUG_ASSERT(inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE); DBUG_ASSERT(inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK);
table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE); table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE);
} }
} }
@ -9389,7 +9402,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
supports auto-partitioning as such engines can do some changes supports auto-partitioning as such engines can do some changes
using in-place API. using in-place API.
*/ */
if ((thd->variables.old_alter_table && if ((thd->variables.alter_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_COPY &&
alter_info->requested_algorithm != alter_info->requested_algorithm !=
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|| is_inplace_alter_impossible(table, create_info, alter_info) || is_inplace_alter_impossible(table, create_info, alter_info)
@ -9597,74 +9610,32 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
goto err_new_table_cleanup; goto err_new_table_cleanup;
thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->count_cuted_fields= CHECK_FIELD_IGNORE;
if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
ha_alter_info.online= true;
// Ask storage engine whether to use copy or in-place // Ask storage engine whether to use copy or in-place
enum_alter_inplace_result inplace_supported= enum_alter_inplace_result inplace_supported=
table->file->check_if_supported_inplace_alter(altered_table, table->file->check_if_supported_inplace_alter(altered_table,
&ha_alter_info); &ha_alter_info);
switch (inplace_supported) { if (alter_info->supports_algorithm(thd, inplace_supported, &ha_alter_info) ||
case HA_ALTER_INPLACE_EXCLUSIVE_LOCK: alter_info->supports_lock(thd, inplace_supported, &ha_alter_info))
// If SHARED lock and no particular algorithm was requested, use COPY. {
if (alter_info->requested_lock ==
Alter_info::ALTER_TABLE_LOCK_SHARED &&
alter_info->requested_algorithm ==
Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
{
use_inplace= false;
}
// Otherwise, if weaker lock was requested, report errror.
else if (alter_info->requested_lock ==
Alter_info::ALTER_TABLE_LOCK_NONE ||
alter_info->requested_lock ==
Alter_info::ALTER_TABLE_LOCK_SHARED)
{
ha_alter_info.report_unsupported_error("LOCK=NONE/SHARED",
"LOCK=EXCLUSIVE");
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
break;
case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
case HA_ALTER_INPLACE_SHARED_LOCK:
// If weaker lock was requested, report errror.
if (alter_info->requested_lock ==
Alter_info::ALTER_TABLE_LOCK_NONE)
{
ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
break;
case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
case HA_ALTER_INPLACE_NO_LOCK:
break;
case HA_ALTER_INPLACE_NOT_SUPPORTED:
// If INPLACE was requested, report error.
if (alter_info->requested_algorithm ==
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
{
ha_alter_info.report_unsupported_error("ALGORITHM=INPLACE",
"ALGORITHM=COPY");
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
// COPY with LOCK=NONE is not supported, no point in trying.
if (alter_info->requested_lock ==
Alter_info::ALTER_TABLE_LOCK_NONE)
{
ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup;
}
// Otherwise use COPY
use_inplace= false;
break;
case HA_ALTER_ERROR:
default:
thd->drop_temporary_table(altered_table, NULL, false); thd->drop_temporary_table(altered_table, NULL, false);
goto err_new_table_cleanup; goto err_new_table_cleanup;
} }
// If SHARED lock and no particular algorithm was requested, use COPY.
if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK &&
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED &&
alter_info->requested_algorithm ==
Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT &&
thd->variables.alter_algorithm ==
Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
use_inplace= false;
if (inplace_supported == HA_ALTER_INPLACE_NOT_SUPPORTED)
use_inplace= false;
if (use_inplace) if (use_inplace)
{ {
table->s->frm_image= &frm; table->s->frm_image= &frm;

View File

@ -2371,9 +2371,19 @@ static Sys_var_mybool Sys_old_mode(
"old", "Use compatible behavior from previous MariaDB version. See also --old-mode", "old", "Use compatible behavior from previous MariaDB version. See also --old-mode",
SESSION_VAR(old_mode), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); SESSION_VAR(old_mode), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
static Sys_var_mybool Sys_old_alter_table( static const char *alter_algorithm_modes[]= {"DEFAULT", "COPY", "INPLACE",
"old_alter_table", "Use old, non-optimized alter table", "NOCOPY", "INSTANT", NULL};
SESSION_VAR(old_alter_table), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
static Sys_var_enum Sys_alter_algorithm(
"alter_algorithm", "Specify the alter table algorithm",
SESSION_VAR(alter_algorithm), CMD_LINE(OPT_ARG),
alter_algorithm_modes, DEFAULT(0));
static Sys_var_enum Sys_old_alter_table(
"old_alter_table", "Alias for alter_algorithm. "
"Deprecated. Use --alter-algorithm instead.",
SESSION_VAR(alter_algorithm), CMD_LINE(OPT_ARG),
alter_algorithm_modes, DEFAULT(0));
static bool check_old_passwords(sys_var *self, THD *thd, set_var *var) static bool check_old_passwords(sys_var *self, THD *thd, set_var *var)
{ {

View File

@ -6882,12 +6882,12 @@ bool ha_connect::NoFieldOptionChange(TABLE *tab)
@retval HA_ALTER_ERROR Unexpected error. @retval HA_ALTER_ERROR Unexpected error.
@retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy. @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy.
@retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock. @retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock.
@retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE @retval HA_ALTER_INPLACE_COPY_LOCK
Supported, but requires SNW lock Supported, but requires SNW lock
during main phase. Prepare phase during main phase. Prepare phase
requires X lock. requires X lock.
@retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock. @retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock.
@retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE @retval HA_ALTER_INPLACE_COPY_NO_LOCK
Supported, concurrent reads/writes Supported, concurrent reads/writes
allowed. However, prepare phase allowed. However, prepare phase
requires X lock. requires X lock.

View File

@ -298,12 +298,24 @@ public:
by ALTER TABLE and holding data used during in-place alter. by ALTER TABLE and holding data used during in-place alter.
@retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported
@retval HA_ALTER_INPLACE_NO_LOCK Supported @retval HA_ALTER_INPLACE_INSTANT
@retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE MDL_EXCLUSIVE is needed for executing prepare_inplace_alter_table()
Supported, but requires lock during main phase and and commit_inplace_alter_table(). inplace_alter_table()
exclusive lock during prepare phase. will not be called.
@retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE @retval HA_ALTER_INPLACE_COPY_NO_LOCK
Supported, prepare phase requires exclusive lock. */ MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
to LOCK=NONE for rebuilding the table in inplace_alter_table()
@retval HA_ALTER_INPLACE_COPY_LOCK
MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
to LOCK=SHARED for rebuilding the table in inplace_alter_table()
@retval HA_ALTER_INPLACE_NOCOPY_NO_LOCK
MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
to LOCK=NONE for inplace_alter_table() which will not rebuild the table
@retval HA_ALTER_INPLACE_NOCOPY_LOCK
MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
to LOCK=SHARED for inplace_alter_table() which will not rebuild
the table. */
enum_alter_inplace_result check_if_supported_inplace_alter( enum_alter_inplace_result check_if_supported_inplace_alter(
TABLE* altered_table, TABLE* altered_table,
Alter_inplace_info* ha_alter_info); Alter_inplace_info* ha_alter_info);

View File

@ -115,17 +115,21 @@ static const alter_table_operations INNOBASE_FOREIGN_OPERATIONS
/** Operations that InnoDB cares about and can perform without rebuild */ /** Operations that InnoDB cares about and can perform without rebuild */
static const alter_table_operations INNOBASE_ALTER_NOREBUILD static const alter_table_operations INNOBASE_ALTER_NOREBUILD
= INNOBASE_ONLINE_CREATE = INNOBASE_ONLINE_CREATE
| INNOBASE_FOREIGN_OPERATIONS
| ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX | ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX
| ALTER_DROP_UNIQUE_INDEX | ALTER_DROP_UNIQUE_INDEX
#ifdef MYSQL_RENAME_INDEX #ifdef MYSQL_RENAME_INDEX
| ALTER_RENAME_INDEX | ALTER_RENAME_INDEX
#endif #endif
;
/** Operations that can be performed instantly, without inplace_alter_table() */
static const alter_table_operations INNOBASE_ALTER_INSTANT
= ALTER_VIRTUAL_COLUMN_ORDER
| ALTER_COLUMN_NAME | ALTER_COLUMN_NAME
| ALTER_COLUMN_EQUAL_PACK_LENGTH
| ALTER_ADD_VIRTUAL_COLUMN | ALTER_ADD_VIRTUAL_COLUMN
| ALTER_DROP_VIRTUAL_COLUMN | INNOBASE_FOREIGN_OPERATIONS
| ALTER_VIRTUAL_COLUMN_ORDER; | ALTER_COLUMN_EQUAL_PACK_LENGTH
| ALTER_DROP_VIRTUAL_COLUMN;
static const alter_table_operations INNOBASE_DEFAULTS static const alter_table_operations INNOBASE_DEFAULTS
= ALTER_COLUMN_NOT_NULLABLE = ALTER_COLUMN_NOT_NULLABLE
@ -526,7 +530,8 @@ innobase_need_rebuild(
const Alter_inplace_info* ha_alter_info, const Alter_inplace_info* ha_alter_info,
const TABLE* table) const TABLE* table)
{ {
if ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) if ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE
| INNOBASE_ALTER_INSTANT))
== ALTER_CHANGE_CREATE_OPTION) { == ALTER_CHANGE_CREATE_OPTION) {
return create_option_need_rebuild(ha_alter_info, table); return create_option_need_rebuild(ha_alter_info, table);
} }
@ -722,30 +727,125 @@ static bool set_default_value(Field* field)
return false; return false;
} }
/** Check whether the table has the FTS_DOC_ID column
@param[in] table InnoDB table with fulltext index
@param[in] altered_table MySQL table with fulltext index
@param[out] fts_doc_col_no The column number for Doc ID,
or ULINT_UNDEFINED if it is of wrong type
@param[out] num_v Number of virtual column
@param[in] check_only check only whether fts doc id exist.
@return whether there exists an FTS_DOC_ID column */
static
bool
innobase_fts_check_doc_id_col(
const dict_table_t* table,
const TABLE* altered_table,
ulint* fts_doc_col_no,
ulint* num_v,
bool check_only=false)
{
*fts_doc_col_no = ULINT_UNDEFINED;
const uint n_cols = altered_table->s->fields;
ulint i;
int err = 0;
*num_v = 0;
for (i = 0; i < n_cols; i++) {
const Field* field = altered_table->field[i];
if (innobase_is_v_fld(field)) {
(*num_v)++;
}
if (my_strcasecmp(system_charset_info,
field->field_name.str, FTS_DOC_ID_COL_NAME)) {
continue;
}
if (strcmp(field->field_name.str, FTS_DOC_ID_COL_NAME)) {
err = ER_WRONG_COLUMN_NAME;
} else if (field->type() != MYSQL_TYPE_LONGLONG
|| field->pack_length() != 8
|| field->real_maybe_null()
|| !(field->flags & UNSIGNED_FLAG)
|| innobase_is_v_fld(field)) {
err = ER_INNODB_FT_WRONG_DOCID_COLUMN;
} else {
*fts_doc_col_no = i - *num_v;
}
if (err && !check_only) {
my_error(err, MYF(0), field->field_name.str);
}
return(true);
}
if (!table) {
return(false);
}
/* Not to count the virtual columns */
i -= *num_v;
for (; i + DATA_N_SYS_COLS < (uint) table->n_cols; i++) {
const char* name = dict_table_get_col_name(table, i);
if (strcmp(name, FTS_DOC_ID_COL_NAME) == 0) {
#ifdef UNIV_DEBUG
const dict_col_t* col;
col = dict_table_get_nth_col(table, i);
/* Because the FTS_DOC_ID does not exist in
the MySQL data dictionary, this must be the
internally created FTS_DOC_ID column. */
ut_ad(col->mtype == DATA_INT);
ut_ad(col->len == 8);
ut_ad(col->prtype & DATA_NOT_NULL);
ut_ad(col->prtype & DATA_UNSIGNED);
#endif /* UNIV_DEBUG */
*fts_doc_col_no = i;
return(true);
}
}
return(false);
}
/** Check if InnoDB supports a particular alter table in-place /** Check if InnoDB supports a particular alter table in-place
@param altered_table TABLE object for new version of table. @param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done @param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data used during in-place alter. by ALTER TABLE and holding data used during in-place alter.
@retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported
@retval HA_ALTER_INPLACE_NO_LOCK Supported @retval HA_ALTER_INPLACE_INSTANT
@retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE Supported, but requires MDL_EXCLUSIVE is needed for executing prepare_inplace_alter_table()
lock during main phase and exclusive lock during prepare phase. and commit_inplace_alter_table(). inplace_alter_table() will not be called.
@retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE Supported, prepare phase @retval HA_ALTER_INPLACE_COPY_NO_LOCK
requires exclusive lock (any transactions that have accessed the table MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded to
must commit or roll back first, and no transactions can access the table LOCK=NONE for rebuilding the table in inplace_alter_table()
while prepare_inplace_alter_table() is executing) @retval HA_ALTER_INPLACE_COPY_LOCK
MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded to
LOCK=SHARED for rebuilding the table in inplace_alter_table()
@retval HA_ALTER_INPLACE_NOCOPY_NO_LOCK
MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded to
LOCK=NONE for inplace_alter_table() which will not rebuild the table
@retval HA_ALTER_INPLACE_NOCOPY_LOCK
MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded to
LOCK=SHARED for inplace_alter_table() which will not rebuild the table
*/ */
enum_alter_inplace_result enum_alter_inplace_result
ha_innobase::check_if_supported_inplace_alter( ha_innobase::check_if_supported_inplace_alter(
/*==========================================*/
TABLE* altered_table, TABLE* altered_table,
Alter_inplace_info* ha_alter_info) Alter_inplace_info* ha_alter_info)
{ {
DBUG_ENTER("check_if_supported_inplace_alter"); DBUG_ENTER("check_if_supported_inplace_alter");
if ((table->versioned(VERS_TIMESTAMP) || altered_table->versioned(VERS_TIMESTAMP)) if ((table->versioned(VERS_TIMESTAMP)
|| altered_table->versioned(VERS_TIMESTAMP))
&& innobase_need_rebuild(ha_alter_info, table)) { && innobase_need_rebuild(ha_alter_info, table)) {
ha_alter_info->unsupported_reason = ha_alter_info->unsupported_reason =
"Not implemented for system-versioned tables"; "Not implemented for system-versioned tables";
@ -780,6 +880,7 @@ ha_innobase::check_if_supported_inplace_alter(
if (ha_alter_info->handler_flags if (ha_alter_info->handler_flags
& ~(INNOBASE_INPLACE_IGNORE & ~(INNOBASE_INPLACE_IGNORE
| INNOBASE_ALTER_INSTANT
| INNOBASE_ALTER_NOREBUILD | INNOBASE_ALTER_NOREBUILD
| INNOBASE_ALTER_REBUILD)) { | INNOBASE_ALTER_REBUILD)) {
@ -788,6 +889,7 @@ ha_innobase::check_if_supported_inplace_alter(
ha_alter_info->unsupported_reason = my_get_err_msg( ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE); ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE);
} }
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
} }
@ -809,7 +911,7 @@ ha_innobase::check_if_supported_inplace_alter(
#endif #endif
if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) { if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK); DBUG_RETURN(HA_ALTER_INPLACE_INSTANT);
} }
/* Only support NULL -> NOT NULL change if strict table sql_mode /* Only support NULL -> NOT NULL change if strict table sql_mode
@ -865,8 +967,9 @@ ha_innobase::check_if_supported_inplace_alter(
*/ */
for (ulint i = 0, icol= 0; i < table->s->fields; i++) { for (ulint i = 0, icol= 0; i < table->s->fields; i++) {
const Field* field = table->field[i]; const Field* field = table->field[i];
const dict_col_t* col = dict_table_get_nth_col(m_prebuilt->table, icol); const dict_col_t* col = dict_table_get_nth_col(
ulint unsigned_flag; m_prebuilt->table, icol);
ulint unsigned_flag;
if (!field->stored_in_db()) { if (!field->stored_in_db()) {
continue; continue;
@ -874,7 +977,8 @@ ha_innobase::check_if_supported_inplace_alter(
icol++; icol++;
if (col->mtype != get_innobase_type_from_mysql_type(&unsigned_flag, field)) { if (col->mtype != get_innobase_type_from_mysql_type(
&unsigned_flag, field)) {
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
} }
@ -942,7 +1046,7 @@ ha_innobase::check_if_supported_inplace_alter(
/* We should be able to do the operation in-place. /* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE). */ See if we can do it online (LOCK=NONE). */
bool online = true; bool online = true;
List_iterator_fast<Create_field> cf_it( List_iterator_fast<Create_field> cf_it(
ha_alter_info->alter_info->create_list); ha_alter_info->alter_info->create_list);
@ -964,7 +1068,8 @@ ha_innobase::check_if_supported_inplace_alter(
} }
for (KEY_PART_INFO* key_part = new_key->key_part; for (KEY_PART_INFO* key_part = new_key->key_part;
key_part < new_key->key_part + new_key->user_defined_key_parts; key_part < (new_key->key_part
+ new_key->user_defined_key_parts);
key_part++) { key_part++) {
const Create_field* new_field; const Create_field* new_field;
@ -1023,8 +1128,12 @@ ha_innobase::check_if_supported_inplace_alter(
column values during online ALTER. */ column values during online ALTER. */
DBUG_ASSERT(key_part->field == altered_table DBUG_ASSERT(key_part->field == altered_table
-> found_next_number_field); -> found_next_number_field);
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC); if (ha_alter_info->online) {
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC);
}
online = false; online = false;
} }
@ -1040,20 +1149,25 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
} }
ha_alter_info->unsupported_reason = if (ha_alter_info->online
MSG_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN; && !ha_alter_info->unsupported_reason) {
ha_alter_info->unsupported_reason =
MSG_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN;
}
online = false; online = false;
} }
} }
} }
DBUG_ASSERT(!m_prebuilt->table->fts || m_prebuilt->table->fts->doc_col DBUG_ASSERT(!m_prebuilt->table->fts
<= table->s->fields); || (m_prebuilt->table->fts->doc_col <= table->s->fields));
DBUG_ASSERT(!m_prebuilt->table->fts || m_prebuilt->table->fts->doc_col
< dict_table_get_n_user_cols(m_prebuilt->table));
if (m_prebuilt->table->fts DBUG_ASSERT(!m_prebuilt->table->fts
&& innobase_fulltext_exist(altered_table)) { || (m_prebuilt->table->fts->doc_col
< dict_table_get_n_user_cols(m_prebuilt->table)));
if (m_prebuilt->table->fts && innobase_fulltext_exist(altered_table)) {
/* FULLTEXT indexes are supposed to remain. */ /* FULLTEXT indexes are supposed to remain. */
/* Disallow DROP INDEX FTS_DOC_ID_INDEX */ /* Disallow DROP INDEX FTS_DOC_ID_INDEX */
@ -1187,16 +1301,17 @@ next_column:
== n_stored_cols == n_stored_cols
&& m_prebuilt->table->supports_instant() && m_prebuilt->table->supports_instant()
&& instant_alter_column_possible(ha_alter_info, table)) { && instant_alter_column_possible(ha_alter_info, table)) {
/* We can perform instant ADD COLUMN, because all
columns are going to be added after existing ones
(and not after hidden InnoDB columns, such as FTS_DOC_ID). */
/* MDEV-14246 FIXME: return HA_ALTER_INPLACE_NO_LOCK and DBUG_RETURN(HA_ALTER_INPLACE_INSTANT);
perform all work in ha_innobase::commit_inplace_alter_table(),
to avoid an unnecessary MDL upgrade/downgrade cycle. */
DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE);
} }
if (!(ha_alter_info->handler_flags & ~(INNOBASE_ALTER_INSTANT
| INNOBASE_INPLACE_IGNORE))) {
DBUG_RETURN(HA_ALTER_INPLACE_INSTANT);
}
bool fts_need_rebuild = false;
if (!online) { if (!online) {
/* We already determined that only a non-locking /* We already determined that only a non-locking
operation is possible. */ operation is possible. */
@ -1213,28 +1328,31 @@ next_column:
refuse to rebuild the table natively altogether. */ refuse to rebuild the table natively altogether. */
if (m_prebuilt->table->fts) { if (m_prebuilt->table->fts) {
cannot_create_many_fulltext_index: cannot_create_many_fulltext_index:
ha_alter_info->unsupported_reason = my_get_err_msg( ha_alter_info->unsupported_reason =
ER_INNODB_FT_LIMIT); my_get_err_msg(ER_INNODB_FT_LIMIT);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
} }
if (innobase_spatial_exist(altered_table)) { if (ha_alter_info->online
ha_alter_info->unsupported_reason = && !ha_alter_info->unsupported_reason) {
my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); if (innobase_spatial_exist(altered_table)) {
} else if (!innobase_fulltext_exist(altered_table)) { ha_alter_info->unsupported_reason = my_get_err_msg(
/* MDEV-14341 FIXME: Remove this limitation. */ ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS);
ha_alter_info->unsupported_reason = } else if (!innobase_fulltext_exist(altered_table)) {
"online rebuild with indexed virtual columns"; /* MDEV-14341 FIXME: Remove this limitation. */
} else { ha_alter_info->unsupported_reason =
ha_alter_info->unsupported_reason = "online rebuild with indexed virtual columns";
my_get_err_msg( } else {
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS); ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
}
} }
} }
if (ha_alter_info->handler_flags if (ha_alter_info->handler_flags
& ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX) { & ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX) {
/* ADD FULLTEXT|SPATIAL INDEX requires a lock. /* ADD FULLTEXT|SPATIAL INDEX requires a lock.
We could do ADD FULLTEXT INDEX without a lock if the We could do ADD FULLTEXT INDEX without a lock if the
@ -1259,30 +1377,72 @@ cannot_create_many_fulltext_index:
if (add_fulltext) { if (add_fulltext) {
goto cannot_create_many_fulltext_index; goto cannot_create_many_fulltext_index;
} }
add_fulltext = true; add_fulltext = true;
ha_alter_info->unsupported_reason = my_get_err_msg( if (ha_alter_info->online
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS); && !ha_alter_info->unsupported_reason) {
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
}
online = false; online = false;
/* Full text search index exists, check
whether the table already has DOC ID column.
If not, InnoDB have to rebuild the table to
add a Doc ID hidden column and change
primary index. */
ulint fts_doc_col_no;
ulint num_v = 0;
fts_need_rebuild =
!innobase_fts_check_doc_id_col(
m_prebuilt->table,
altered_table,
&fts_doc_col_no, &num_v, true);
} }
if (online && (key->flags & HA_SPATIAL)) { if (online && (key->flags & HA_SPATIAL)) {
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); if (ha_alter_info->online) {
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS);
}
online = false; online = false;
} }
} }
} }
// FIXME: implement Online DDL for system-versioned tables // FIXME: implement Online DDL for system-versioned tables
if ((table->versioned(VERS_TRX_ID) || altered_table->versioned(VERS_TRX_ID)) if ((table->versioned(VERS_TRX_ID)
|| altered_table->versioned(VERS_TRX_ID))
&& innobase_need_rebuild(ha_alter_info, table)) { && innobase_need_rebuild(ha_alter_info, table)) {
ha_alter_info->unsupported_reason =
"Not implemented for system-versioned tables"; if (ha_alter_info->online) {
ha_alter_info->unsupported_reason =
"Not implemented for system-versioned tables";
}
online = false; online = false;
} }
if (fts_need_rebuild || innobase_need_rebuild(ha_alter_info, table)) {
DBUG_RETURN(online
? HA_ALTER_INPLACE_COPY_NO_LOCK
: HA_ALTER_INPLACE_COPY_LOCK);
}
if (ha_alter_info->unsupported_reason) {
} else if (ha_alter_info->handler_flags & INNOBASE_ONLINE_CREATE) {
ha_alter_info->unsupported_reason = "ADD INDEX";
} else {
ha_alter_info->unsupported_reason = "DROP INDEX";
}
DBUG_RETURN(online DBUG_RETURN(online
? HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE ? HA_ALTER_INPLACE_NOCOPY_NO_LOCK
: HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE); : HA_ALTER_INPLACE_NOCOPY_LOCK);
} }
/*************************************************************//** /*************************************************************//**
@ -2481,92 +2641,6 @@ innobase_create_index_def(
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*******************************************************************//**
Check whether the table has the FTS_DOC_ID column
@return whether there exists an FTS_DOC_ID column */
static
bool
innobase_fts_check_doc_id_col(
/*==========================*/
const dict_table_t* table, /*!< in: InnoDB table with
fulltext index */
const TABLE* altered_table,
/*!< in: MySQL table with
fulltext index */
ulint* fts_doc_col_no,
/*!< out: The column number for
Doc ID, or ULINT_UNDEFINED
if it is of wrong type */
ulint* num_v) /*!< out: number of virtual column */
{
*fts_doc_col_no = ULINT_UNDEFINED;
const uint n_cols = altered_table->s->fields;
ulint i;
*num_v = 0;
for (i = 0; i < n_cols; i++) {
const Field* field = altered_table->field[i];
if (innobase_is_v_fld(field)) {
(*num_v)++;
}
if (my_strcasecmp(system_charset_info,
field->field_name.str, FTS_DOC_ID_COL_NAME)) {
continue;
}
if (strcmp(field->field_name.str, FTS_DOC_ID_COL_NAME)) {
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
field->field_name.str);
} else if (field->type() != MYSQL_TYPE_LONGLONG
|| field->pack_length() != 8
|| field->real_maybe_null()
|| !(field->flags & UNSIGNED_FLAG)
|| innobase_is_v_fld(field)) {
my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0),
field->field_name.str);
} else {
*fts_doc_col_no = i - *num_v;
}
return(true);
}
if (!table) {
return(false);
}
/* Not to count the virtual columns */
i -= *num_v;
for (; i + DATA_N_SYS_COLS < (uint) table->n_cols; i++) {
const char* name = dict_table_get_col_name(table, i);
if (strcmp(name, FTS_DOC_ID_COL_NAME) == 0) {
#ifdef UNIV_DEBUG
const dict_col_t* col;
col = dict_table_get_nth_col(table, i);
/* Because the FTS_DOC_ID does not exist in
the MySQL data dictionary, this must be the
internally created FTS_DOC_ID column. */
ut_ad(col->mtype == DATA_INT);
ut_ad(col->len == 8);
ut_ad(col->prtype & DATA_NOT_NULL);
ut_ad(col->prtype & DATA_UNSIGNED);
#endif /* UNIV_DEBUG */
*fts_doc_col_no = i;
return(true);
}
}
return(false);
}
/*******************************************************************//** /*******************************************************************//**
Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
on the Doc ID column. on the Doc ID column.
@ -6437,7 +6511,8 @@ check_if_ok_to_rename:
n_drop_fk = 0; n_drop_fk = 0;
if (ha_alter_info->handler_flags if (ha_alter_info->handler_flags
& (INNOBASE_ALTER_NOREBUILD | INNOBASE_ALTER_REBUILD)) { & (INNOBASE_ALTER_NOREBUILD | INNOBASE_ALTER_REBUILD
| INNOBASE_ALTER_INSTANT)) {
heap = mem_heap_create(1024); heap = mem_heap_create(1024);
if (ha_alter_info->handler_flags if (ha_alter_info->handler_flags
@ -6738,7 +6813,8 @@ err_exit:
} }
if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)
|| ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) || ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE
| INNOBASE_ALTER_INSTANT))
== ALTER_CHANGE_CREATE_OPTION == ALTER_CHANGE_CREATE_OPTION
&& !create_option_need_rebuild(ha_alter_info, table))) { && !create_option_need_rebuild(ha_alter_info, table))) {
@ -6757,7 +6833,7 @@ err_exit:
} }
DBUG_ASSERT(m_prebuilt->trx->dict_operation_lock_mode == 0); DBUG_ASSERT(m_prebuilt->trx->dict_operation_lock_mode == 0);
if (ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) { if (ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE)) {
online_retry_drop_indexes( online_retry_drop_indexes(
m_prebuilt->table, m_user_thd); m_prebuilt->table, m_user_thd);
@ -6801,6 +6877,7 @@ err_exit:
HA_ERR_WRONG_INDEX, HA_ERR_WRONG_INDEX,
"InnoDB rebuilding table to add" "InnoDB rebuilding table to add"
" column " FTS_DOC_ID_COL_NAME); " column " FTS_DOC_ID_COL_NAME);
} else if (fts_doc_col_no == ULINT_UNDEFINED) { } else if (fts_doc_col_no == ULINT_UNDEFINED) {
goto err_exit; goto err_exit;
} }

View File

@ -893,8 +893,8 @@ row_undo_mod_upd_del_sec(
} }
/* During online index creation, /* During online index creation,
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE should HA_ALTER_INPLACE_COPY_NO_LOCK or HA_ALTER_INPLACE_NOCOPY_NO_LOCk
guarantee that any active transaction has not modified should guarantee that any active transaction has not modified
indexed columns such that col->ord_part was 0 at the indexed columns such that col->ord_part was 0 at the
time when the undo log record was written. When we get time when the undo log record was written. When we get
to roll back an undo log entry TRX_UNDO_DEL_MARK_REC, to roll back an undo log entry TRX_UNDO_DEL_MARK_REC,
@ -959,8 +959,8 @@ row_undo_mod_del_mark_sec(
} }
/* During online index creation, /* During online index creation,
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE should HA_ALTER_INPLACE_COPY_NO_LOCK or HA_ALTER_INPLACE_NOCOPY_NO_LOCK
guarantee that any active transaction has not modified should guarantee that any active transaction has not modified
indexed columns such that col->ord_part was 0 at the indexed columns such that col->ord_part was 0 at the
time when the undo log record was written. When we get time when the undo log record was written. When we get
to roll back an undo log entry TRX_UNDO_DEL_MARK_REC, to roll back an undo log entry TRX_UNDO_DEL_MARK_REC,

View File

@ -11053,16 +11053,17 @@ my_core::enum_alter_inplace_result ha_rocksdb::check_if_supported_inplace_alter(
DBUG_RETURN(my_core::HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(my_core::HA_ALTER_INPLACE_NOT_SUPPORTED);
} }
DBUG_RETURN(my_core::HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE); /* FIXME: MDEV-16099 Use alter algorithm=nocopy or algorithm=instant
for non-InnoDB engine */
DBUG_RETURN(my_core::HA_ALTER_INPLACE_COPY_LOCK);
} }
/** /**
Allows the storage engine to update internal structures with concurrent Allows the storage engine to update internal structures with concurrent
writes blocked. If check_if_supported_inplace_alter() returns writes blocked. If check_if_supported_inplace_alter() returns
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE or HA_ALTER_INPLACE_COPY_NO_LOCK or HA_ALTER_INPLACE_COPY_LOCK.
HA_ALTER_INPLACE_SHARED_AFTER_PREPARE, this function is called with this function is called with exclusive lock otherwise the same level of
exclusive lock otherwise the same level of locking as for locking as for inplace_alter_table() will be used.
inplace_alter_table() will be used.
@note Storage engines are responsible for reporting any errors by @note Storage engines are responsible for reporting any errors by
calling my_error()/print_error() calling my_error()/print_error()

View File

@ -257,13 +257,13 @@ static bool only_flags(ulong bits, ulong mask) {
// HA_ALTER_INPLACE_EXCLUSIVE_LOCK: prepare and alter runs with MDL X // HA_ALTER_INPLACE_EXCLUSIVE_LOCK: prepare and alter runs with MDL X
// HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE: prepare runs with MDL X, // HA_ALTER_INPLACE_COPY_LOCK: prepare runs with MDL X,
// alter runs with MDL SNW // alter runs with MDL SNW
// HA_ALTER_INPLACE_SHARED_LOCK: prepare and alter methods called with MDL SNW, // HA_ALTER_INPLACE_SHARED_LOCK: prepare and alter methods called with MDL SNW,
// concurrent reads, no writes // concurrent reads, no writes
// HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE: prepare runs with MDL X, // HA_ALTER_INPLACE_COPY_NO_LOCK: prepare runs with MDL X,
// alter runs with MDL SW // alter runs with MDL SW
// HA_ALTER_INPLACE_NO_LOCK: prepare and alter methods called with MDL SW, // HA_ALTER_INPLACE_NO_LOCK: prepare and alter methods called with MDL SW,
@ -319,7 +319,9 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
// we grab an exclusive MDL for the drop index. // we grab an exclusive MDL for the drop index.
result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK; result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
} else { } else {
result = HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE; /* FIXME: MDEV-16099 Use alter algorithm=nocopy
or algorithm=instant for non-InnoDB engine */
result = HA_ALTER_INPLACE_COPY_LOCK;
// someday, allow multiple hot indexes via alter table add key. // someday, allow multiple hot indexes via alter table add key.
// don't forget to change the store_lock function. // don't forget to change the store_lock function.
@ -336,7 +338,9 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
tokudb::sysvars::create_index_online(thd)) { tokudb::sysvars::create_index_online(thd)) {
// external_lock set WRITE_ALLOW_WRITE which allows writes // external_lock set WRITE_ALLOW_WRITE which allows writes
// concurrent with the index creation // concurrent with the index creation
result = HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE; /* FIXME: MDEV-16099 Use alter algorithm=nocopy
or algorithm=instant for non-InnoDB engine */
result = HA_ALTER_INPLACE_COPY_NO_LOCK;
} }
} }
} }
@ -509,7 +513,9 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
ALTER_RECREATE_TABLE | ALTER_RECREATE_TABLE |
ALTER_COLUMN_DEFAULT)) { ALTER_COLUMN_DEFAULT)) {
ctx->optimize_needed = true; ctx->optimize_needed = true;
result = HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE; /* FIXME: MDEV-16099 Use alter algorithm=nocopy
or algorithm=instant for non-InnoDB engine */
result = HA_ALTER_INPLACE_COPY_NO_LOCK;
} }
#endif #endif