情境
假設
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,因此唯一的影響一樣只是查詢被阻塞一段時間。