情境
假設
C10、C20
為 gh-ost
所使用的連結, C1..C9
、 C11..C19
、 C21..C29
為其他連線。C1..C9
:對原表(tb1)
進行INSERT、UPDATE、DELETE
等DML操作
C10
:CREATE TABLE tb1_old(id int primary key) COMMENT='magic-be-here'
C10
:LOCK TABLES tb1 WRITE, tb1_old WRITE
C11..C19
:新的連線對tb1
進行DML操作,但由於tb1
被LOCK
住而阻塞
C20
:RENAME TABLE tbl TO tbl_old, ghost TO tbl
,雖然因為LOCK
此操作會被阻塞,但在阻塞的對列中優先級會高於C1..C9
和C11..C19
C21..C29
:新的連線對tb1
進行DML操作,但由於tb1
被LOCK
住而阻塞
C10
:透過show processlist
確認是否有C20的RENAME
操作
C10
:DROP TABLE tbl_old
,什麼事都沒有發生tb1
仍舊被LOCK
C10
:UNLOCK TABLES
最後,阻塞的對列中
RENAME
優先被執行,接下來是 C1..C9
C11..C19
C21..C29
都直接應用到更新後的 tb1
。解析
在 MySQL
中有兩種方式可以 RENAME TABLE
:
RENAME TABLE
:能夠同時rename
多張表,這表示rename
多張表是原子的操作。但在8.0.13
之前無法在同一個 session 同時LOCK
和RENAME
。
ALTER TABLE RENAME
:能夠在LOCK TABLE
的 session 進行,但卻無法一次RENAME
多張表。
tb1_old
的存在,避免Lock
連線死掉後的影響。
Lock Table
避免RENAME
過早執行。
- 在阻塞的對列中,
RENAME
總是優先於INSERT、UPDATE、DELETE
。
失敗的影響
- 如果在
C10 Create table 或 Lock table
失敗,則不會繼續執行後續步驟。
- 如果在
C20 Rename
時C10 Lock連線死亡
,因為tb1_old
的存在Rename
失敗,同時Lock
解除,C1..C9
和C11..C19
正常執行,唯一的影響只有查詢被阻塞了一段時間。
- 如果
C20 Rename
在C10 Drop 或 Unlock
之前死亡,gh-ost
會正常執行Drop、UnLock
,因此唯一的影響一樣只是查詢被阻塞一段時間。