操做 | In Place | Rebuilds Table | Concurrent DML | Only Modifies Metadata | 說明 |
---|---|---|---|---|---|
add/create secondary index | yes | No | yes* | no | 當表上有FULLTEXT索引除外,須要鎖表,阻塞寫 |
drop index | yes | no | yes | yes | - |
add fulltext index | yes | no | no | no | - |
add primary key | yes* | yes | yes | no | 即便in-place,但須要copy data,不過效率比copy方式高 |
drop primary key | no | yes | no | no | 即便in-place,但須要copy data,不過效率比copy方式高 |
Dropping a primary key and adding another | Yes | Yes | Yes | No | - |
add column | yes | yes | yes* | no | 自增列阻塞寫 |
drop column | yes | yes | yes | no | - |
Rename a column | yes | no | yes* | yes | 只改變列名不改變類型才支持寫 |
Reorder columns | yes | yes | yes | no | - |
Set default value for a column | yes | no | yes | yes | - |
Change data type of column | no | yes | no | no | - |
Dropping the column default value | yes | no | yes | yes | - |
Changing the auto-increment value | yes | no | yes | no* | 修改時內存值不是數據文件 |
Making a column NULL | yes | yes | yes | no | - |
Making a column NOT NULL | yes | yes | yes | no | - |
Modifying the definition of an ENUM or SET column | yes | no | yes | yes | - |
Adding a foreign key constraint | yes* | no | yes | yes | INPLACE只有在foreign_key_checks=off |
Dropping a foreign key constraint | yes | no | yes | yes | - |
Changing the ROW_FORMAT | yes | yes | yes | no | — |
Changing the KEY_BLOCK_SIZE | yes | yes | yes | no | — |
Convert character set | no | yes | no | no | - |
optimize table | yes* | yes | yes | no | 從5.6.17支持in-place,但當帶有fulltext index的表用copy table方式而且阻塞寫 |
alter table...engine=innodb | yes* | yes | yes | no | 從5.6.17支持in-place,當帶有fulltext index的表用copy table方式而且阻塞寫 |
Renaming a table | yes | no | yes | yes | - |
操做 | In Place | Rebuilds Table | Concurrent DML | Only Modifies Metadata | 說明 |
---|---|---|---|---|---|
Renaming an index | yes | no | yes | yes | 5.7新增 |
Adding a SPATIAL index | Yes | No | No | No | 5.7新增 |
Extending VARCHAR column size | Yes | No | Yes | Yes | 5.7新增,只能在[0-255],[256-~]字節區間擴大 |
一、擴展varchar長度測試算法
1.1)varchar從大變小session
操做 | In Place | Rebuilds Table | Concurrent DML | Only Modifies Metadata | 說明 |
---|---|---|---|---|---|
varchar從大變小 | no | yes | no | no | 阻塞DML |
1.2) varchar從小變大測試
對於大小爲0到255字節的VARCHAR列,須要一個長度字節來編碼該值。對於大小爲256或更多的字節的VARCHAR列,須要兩個長度字節。 所以,in-place算法更改表只支持將VARCHAR列的大小從0字節增長到255字節,或者從256字節增長到更大的值。 in-place算法不支持將VARCHAR列的大小從小於256字節增長到等於或大於256字節的大小,由於在這種狀況下,所需長度字節的數量從1變化到2,只能經過copy方式實現。 好比將VARARAR(255字節)更改成VARCHAR(256字節),只能copy算法而且阻塞寫
-------------------測試---------------------
```
說明:採用utf8,若是存中文字符,一個字符須要3個字節,所以255字節對應最大字符數是varchar(85),也就是[0-255]對應varchar(0-85),[256-~]對應varchar(86-~)ui
表結構:
create table varchar_test(
c1 varchar(1) not null default '0'
);this
1)採用online方式,擴大到85字符---支持 alter table varchar_test change c1 c1 varchar(85) not null default '0',ALGORITHM=INPLACE, LOCK=NONE; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 2)採用online方式,擴大到86字符---不支持 alter table varchar_test change c1 c1 varchar(86) not null default '0',ALGORITHM=INPLACE, LOCK=NONE; ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. 3)採用copy方式 alter table varchar_test change c1 c1 varchar(86) not null default '0',ALGORITHM=copy; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 4)採用online方式,從86擴大到259字符---支持 alter table varchar_test change c1 c1 varchar(259) not null default '0',ALGORITHM=INPLACE, LOCK=NONE; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0
## 3、8.0版本online DDL(僅列出與5.7不一樣的地方) Operation| Instant |In Place| Rebuilds Table| Permits Concurrent DML| Only Modifies Metadata|desc ---|---|---|---|---|---|---| add column|yes*|yes|yes|yes*|no|自增列阻塞寫 modify index type|yes|yes|no|yes|yes|- **三、實現原理**
目標表T1上MDL(SHARED_NO_WRITE),阻塞全部寫操做 判斷是否符合在線加字段的條件,如符合,執行步驟3,不然按照官方方式來新增字段。 建立跟目標表T1同構的臨時表frm文件S1.frm(含新增字段) 目標表T1的字典鎖升級爲排它鎖,全部關於T1表的全部讀寫操做被阻塞 修改T1表InnoDB內部數據字典信息,增長新字段。 將S1.frm重命名爲T1.frm 釋放表T1的字典鎖
**二、支持instant的ddl**
Change index option
Rename table (in ALTER way)
SET/DROP DEFAULT
MODIFY COLUMN
Add/drop virtual columns
Add columns– We call this instant ADD COLUMN編碼
**四、使用最新算法instant條件:**
1)不能合併寫到其餘不支持instant算法的alter 語句後面;code
alter table sbtest1 add index idx_2(k),add c5 varchar(10) not null default '0' ,ALGORITHM=instant;
ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY/INPLACE.orm
2) 不支持before和after關鍵字,只能默認的加到最後一列;blog
alter table sbtest1 add c2 varchar(10) not null default '0';
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0索引
alter table sbtest1 add c4 varchar(10) not null default '0' after id;
Query OK, 0 rows affected (26.42 sec)
Records: 0 Duplicates: 0 Warnings: 0
alter table sbtest1 add c5 varchar(10) not null default '0' after id,ALGORITHM=instant;
ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY/INPLACE.
3)不支持ROW_FORMAT=COMPRESSED類型的表;
root:sbtest> show table status like 'sbtest1'\G
*************************** 1. row ***************************
Name: sbtest1
Engine: InnoDB
Version: 10
Row_format: Compressed
Rows: 9906340
Avg_row_length: 73
Data_length: 724033536
Max_data_length: 0
Index_length: 101171200
Data_free: 3145728
Auto_increment: 20000020
Create_time: 2018-10-21 15:48:22
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options: max_rows=100000000 row_format=COMPRESSED
Comment:
1 row in set (0.00 sec)
root:sbtest>
root:sbtest> alter table sbtest1 add c5 varchar(10) not null default '0',ALGORITHM=instant;
ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY/INPLACE.
root:sbtest>
4)表上有FULLTEXT index,不支持instant算法;
5)不支持臨時表加字段;
6)若是表上存在大事務,instant也會被阻塞
## 6、官方online ddl限制 ![](https://img2018.cnblogs.com/blog/818283/201811/818283-20181103182516815-346174374.png) **一、大事務可能引發MDL鎖(即便是8.0.12 instant方式也是須要獲取MDL鎖的)**
session 1:
alter table sbtest1 ALGORITHM=INPLACE,drop column c2 ;
session2:寫入事務未提交
set autocommit=0;
begin;
insert into sbtest1(c) values("session2"); --當執行後,session 1將被阻塞,狀態有alter table -->Waiting for table metadata lock
session3:
insert into sbtest1(c) values("session2"); --被阻塞
結論發現:
dbadmin:sbtest> show processlist;
+----------+---------+-----------+--------+---------+------+---------------------------------+------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----------+---------+-----------+--------+---------+------+---------------------------------+------------------------------------------------------+
| 78213439 | dbadmin | localhost | sbtest | Query | 0 | starting | show processlist |
| 78213440 | root | localhost | sbtest | Query | 1763 | Waiting for table metadata lock | alter table sbtest1 ALGORITHM=INPLACE,drop column c2 |
| 78213441 | dbadmin | localhost | sbtest | Query | 1373 | Waiting for table metadata lock | insert into sbtest1(c) values("darren") |
```
通過漫長的時間,發現session2 插入語句被回滾了(由於客戶端鏈接超過30分鐘斷開致使未提交的事務自動回滾),session 1和session 3執行成功。
二、online ddl沒法暫停和進度監控
三、online ddl大表可能致使從庫延遲嚴重