情境

假設 C10、C20gh-ost 所使用的連結, C1..C9C11..C19C21..C29 為其他連線。
  • C1..C9:對 原表(tb1) 進行 INSERT、UPDATE、DELETE 等DML操作
  • C10CREATE TABLE tb1_old(id int primary key) COMMENT='magic-be-here'
  • C10LOCK TABLES tb1 WRITE, tb1_old WRITE
  • C11..C19:新的連線對 tb1進行DML操作,但由於 tb1LOCK住而阻塞
  • C20RENAME TABLE tbl TO tbl_old, ghost TO tbl,雖然因為 LOCK 此操作會被阻塞,但在阻塞的對列中優先級會高於 C1..C9C11..C19
  • C21..C29:新的連線對 tb1進行DML操作,但由於 tb1LOCK住而阻塞
  • C10:透過 show processlist 確認是否有 C20的RENAME 操作
  • C10DROP TABLE tbl_old,什麼事都沒有發生 tb1 仍舊被 LOCK
  • C10UNLOCK TABLES
最後,阻塞的對列中 RENAME 優先被執行,接下來是 C1..C9 C11..C19 C21..C29 都直接應用到更新後的 tb1

解析

MySQL 中有兩種方式可以 RENAME TABLE
  1. RENAME TABLE:能夠同時 rename多張表,這表示 rename多張表是原子的操作。但在 8.0.13 之前無法在同一個 session 同時 LOCKRENAME
  1. ALTER TABLE RENAME:能夠在 LOCK TABLE 的 session 進行,但卻無法一次 RENAME多張表。
  • tb1_old的存在,避免 Lock連線死掉後的影響。
  • Lock Table 避免 RENAME 過早執行。
  • 在阻塞的對列中, RENAME總是優先於 INSERT、UPDATE、DELETE

失敗的影響

  1. 如果在 C10 Create table 或 Lock table失敗,則不會繼續執行後續步驟。
  1. 如果在 C20 RenameC10 Lock連線死亡,因為 tb1_old的存在 Rename失敗,同時 Lock 解除, C1..C9C11..C19正常執行,唯一的影響只有查詢被阻塞了一段時間。
  1. 如果 C20 RenameC10 Drop 或 Unlock之前死亡, gh-ost會正常執行 Drop、UnLock,因此唯一的影響一樣只是查詢被阻塞一段時間。