Original address: https://mysqlserverteam.com/mysql-8-0-innodb-now-supports-instant-add-column/
MySQL 5.6 is the first version to support replace DDL. Before MySQL 5.6, the only way to execute DDL was to copy lines line by line.
INPLACE DDL is mainly processed by InnoDB, while line by line COPY is processed at the server layer. Until 8.0 (see the experimental version), InnoDB even added columns to the table by rebuilding the table for the replace DDL algorithm.
- For large tables, it can take a long time, especially in a replication environment.
- Disk space requirements will more than double, roughly the same size as existing tables.
- DDL operations take up resources, and put forward high requirements for CPU, memory and IO, which compete for resources from user transactions.
- If replication is involved, the slave must wait until the DDL completes before synchronization can start.
Many users asked us how to avoid the time-consuming schema changes. You can now do this by (always) specifying ALGORITHM = install, which guarantees that the operation will complete immediately (if not supported).
In addition, if ALGORITHM is not specified at all, the server will first try the default = install ALGORITHM, if it cannot be completed, the server will try the replace ALGORITHM; if SE cannot support it, the server will finally try the COPY ALGORITHM.
The new syntax is as follows:
ALTER TABLE table_name [alter_specification], ALGORITHM=INSTANT;
This change also affects the LOCK =... Semantics. There is no need to specify a LOCK for the immediate algorithm. If you use ALGORITHM = install, LOCK cannot be set to any value other than DEFAULT, otherwise an error will occur:
ALTER TABLE t1 ALTER COLUMN i SET DEFAULT 11, ALGORITHM=INSTANT, LOCK=NONE; ERROR HY000: Incorrect usage of ALGORITHM=INSTANT and LOCK=NONE/SHARED/EXCLUSIVE # ALGORITHM=INSTANT and LOCK=DEFAULT are OK though. ALTER TABLE t1 ALTER COLUMN i SET DEFAULT 13, ALGORITHM=INSTANT, LOCK=DEFAULT;
ALTER TABLE t1 ALTER COLUMN i SET DEFAULT 12, DROP COLUMN j, ALGORITHM=INSTANT; ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY/INPLACE
Currently, Innodb instant DDL supports the following operations
- Change index option
- Rename table (in ALTER way)
- SET/DROP DEFAULT
- MODIFY COLUMN
- Add/drop virtual columns
- Add columns (non generated) - what we call instant DDL
mysql> CREATE TABLE t1 (a INT, b INT, KEY(b)); Query OK, 0 rows affected (0.70 sec) mysql> # Modify the index can be instant if it's a trivial change mysql> ALTER TABLE t1 DROP KEY b, ADD KEY b(b) USING BTREE, ALGORITHM = INSTANT; Query OK, 0 rows affected (0.14 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> # Rename the table through ALTER TABLE can be instant mysql> ALTER TABLE t1 RENAME TO t2, ALGORITHM = INSTANT; Query OK, 0 rows affected (0.26 sec) mysql> # SET DEFAULT to a column can be instant mysql> ALTER TABLE t2 ALTER COLUMN b SET DEFAULT 100, ALGORITHM = INSTANT; Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> # DROP DEFAULT to a column can be instant mysql> ALTER TABLE t2 ALTER COLUMN b DROP DEFAULT, ALGORITHM = INSTANT; Query OK, 0 rows affected (0.08 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> # MODIFY COLUMN can be instant mysql> ALTER TABLE t2 ADD COLUMN c ENUM('a', 'b', 'c'), ALGORITHM = INSTANT; Query OK, 0 rows affected (0.35 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE t2 MODIFY COLUMN c ENUM('a', 'b', 'c', 'd', 'e'), ALGORITHM=INSTANT; Query OK, 0 rows affected (0.12 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> # ADD/DROP virtual column can be instant mysql> ALTER TABLE t2 ADD COLUMN (d INT GENERATED ALWAYS AS (a + 1) VIRTUAL), ALGORITHM = INSTANT; Query OK, 0 rows affected (0.38 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE t2 DROP COLUMN d, ALGORITHM = INSTANT; Query OK, 0 rows affected (0.40 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> # Do two operations instantly in the same statement mysql> ALTER TABLE t2 ALTER COLUMN a SET DEFAULT 20, ALTER COLUMN b SET DEFAULT 200, ALGORITHM = INSTANT; Query OK, 0 rows affected (0.20 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> DROP TABLE t2; Query OK, 0 rows affected (0.36 sec)
How does it work
The principle of real-time DDL is rather obscure. The following two diagrams can also be described. In a word, compared with the original newly added fields, the whole table can be rebuilt, and the method of instant plus fields can learn to change metadata to improve performance.
2. The process of adding fields in real time: only metadata is modified after the row based storage rule changes (add fields)
,
3. The process of query after "instant" plus fields.
4. Processing of new data after "instant" adding fields
mysql> CREATE TABLE t1 (a INT, b INT); Query OK, 0 rows affected (0.06 sec) mysql> SELECT table_id, name, instant_cols FROM information_schema.innodb_tables WHERE name LIKE '%t1%'; +----------+---------+--------------+ | table_id | name | instant_cols | +----------+---------+--------------+ | 1065 | test/t1 | 0 | +----------+---------+--------------+ 1 row in set (0.22 sec) mysql> SELECT table_id, name, has_default, default_value FROM information_schema.innodb_columns WHERE table_id = 1065; +----------+------+-------------+---------------+ | table_id | name | has_default | default_value | +----------+------+-------------+---------------+ | 1065 | a | 0 | NULL | | 1065 | b | 0 | NULL | +----------+------+-------------+---------------+ 2 rows in set (0.38 sec)
mysql> ALTER TABLE t1 ADD COLUMN c INT, ADD COLUMN d INT DEFAULT 1000, ALGORITHM=INSTANT; Query OK, 0 rows affected (0.07 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SELECT table_id, name, instant_cols FROM information_schema.innodb_tables WHERE name LIKE '%t1%'; +----------+---------+--------------+ | table_id | name | instant_cols | +----------+---------+--------------+ | 1065 | test/t1 | 2 | +----------+---------+--------------+ 1 row in set (0.03 sec) mysql> SELECT table_id, name, has_default, default_value FROM information_schema.innodb_columns WHERE table_id = 1065; +----------+------+-------------+---------------+ | table_id | name | has_default | default_value | +----------+------+-------------+---------------+ | 1065 | a | 0 | NULL | | 1065 | b | 0 | NULL | | 1065 | c | 1 | NULL | | 1065 | d | 1 | 800003e8 | +----------+------+-------------+---------------+ 4 rows in set (0.36 sec)
mysql> ALTER TABLE t1 ADD COLUMN e VARCHAR(100) DEFAULT 'Hello MySQL!'; Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SELECT table_id, name, instant_cols FROM information_schema.innodb_tables WHERE name LIKE '%t1%'; +----------+---------+--------------+ | table_id | name | instant_cols | +----------+---------+--------------+ | 1065 | test/t1 | 2 | +----------+---------+--------------+ 1 row in set (0.03 sec) mysql> SELECT table_id, name, has_default, default_value FROM information_schema.innodb_columns WHERE table_id = 1065; +----------+------+-------------+--------------------------+ | table_id | name | has_default | default_value | +----------+------+-------------+--------------------------+ | 1065 | a | 0 | NULL | | 1065 | b | 0 | NULL | | 1065 | c | 1 | NULL | | 1065 | d | 1 | 800003e8 | | 1065 | e | 1 | 48656c6c6f204d7953514c21 | +----------+------+-------------+--------------------------+ 5 rows in set (0.36 sec)
- In older versions, the row size is pre checked, so ADD COLUMN fails at the beginning. However, with the new immediate ADD COLUMN, the row size will only be checked when the row is later updated.
- In previous versions, if a table or index was corrupted, you could "fix" the problem by rebuilding the table. Adding columns on the fly creates more challenges, and we're looking for ways to mitigate that.
- Only adding columns in one statement is supported, that is, if there are other non install operations in the same statement, they cannot be completed immediately
- Only the last added column is supported, not among existing columns
- Rarely used COMPRESSED row format is not supported
- Tables that already have full-text indexes are not supported
- Any tables in the DD tablespace are not supported (????)
- Temporary tables are not supported (supplied with COPY)