pt-online-schema-change開始一些設置
- SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'
- SET SESSION innodb_lock_wait_timeout=1
- 設置當前會話的ROW級別的鎖timeout,針對的是table中的數據
- SHOW VARIABLES LIKE 'lock_wait_timeout'
- SET SESSION lock_wait_timeout=60
- 設置當前會話的metadata lock的鎖的timeout,針對的是table的DDL表結構信息
- SHOW VARIABLES LIKE 'wait_timeout'
- SET SESSION wait_timeout=10000
- 設置當前會話的連接超時的實際
pt-online-schema-change大致工作流程
- 創建一個新表,表結構和舊錶結構一摸一樣
- 將需要執行的alter table語句在新表執行
- 在原表創建三個觸發器,分別時delete,insert,update的觸發器
- 在修改期間所有舊錶的插入,修改,刪除都會在新表重放一次。
- 以一定的大小依次的將數據從舊錶拷貝到新表
- 這個大小並不是以rows爲單位,而是以chunk爲單位。即是物理大小
- 插入新表的語句是類似於insert ... new_table select ... old_table force index('primary') where ..... LOCK IN SHARE MODE 在插入新表的過程會添加共享鎖,所以這部分的數據在插入過程中是不允許寫入,修改和刪除的。
- 新表寫入完畢之後,Rename 原表到old表中,在把新表Rename爲原表
- 如果有參考該表的外鍵,根據alter-foreign-keys-method參數的值,檢測外鍵相關的表,做相應設置的處理
- 默認刪除舊錶
pt-online-schema-change參數介紹
- --host , --user , --passsword
- DDL操作的MySQL實例連接,若是不想在命令行顯示輸入密碼的話,可以使用 --ask-pass手動輸入MySQL的實例信息。
- --alter
- 後面接的是沒有alter table關鍵字的DDL的語句,多個話可以使用逗號隔開。例如
modify column col1 new_datatype
- 絕大部分的情況下表需要主鍵或者唯一索引,因爲工作的過程中爲了保證新表也是最新的,需要在舊錶上面創建DELETE,UPDATE的觸發器,同步到新表的時候存在主鍵速度會更快。個別情況是當alter操作就是在column1上面創建主鍵的時候,DELETE觸發器將基於column1列。
- 子句不支持去rename重命名
- 5.7之前online不支持在線給索引重命名,需要先drop再create。pt-osc也一樣
- 子句如果是add column設置default not null必須設置默認值,否則的話會報錯
- 如果刪除外鍵名(fk_foo),使用工具的時候外鍵名要加下劃線,比如
--alter "DROP FOREIGN KEY _fk_foo"
- 後面接的是沒有alter table關鍵字的DDL的語句,多個話可以使用逗號隔開。例如
- D=db_name,t=table_name
- 制定需要修改的數據庫名和表
- --max-load
- 默認的Thread_running=25。在每個chunk拷貝完成之後,都會執行show global status,檢查指標是否超過了閥值,如果超過,則先暫停。這裏可以用逗號分隔,指定多個條件,每個條件的格式:status指標=MAX_VALUE或者status指標:MAX_VALUE。如果不指定MAX_VALUE,那麼這個工具的閥值默認就是當前值的120%。
- --max-lag
- 默認值是1s。在每個chunk拷貝完畢之後,都會去獲取所有slave的延遲信息(Seconds_Behind_Master),當延遲的值是大於設置的值的話,那麼會暫停複製,等待延遲的值小於這個設置的值。這個參數和
--check-interval
一起聯合使用,定義的是當休眠多長時間之後再去獲取所有slave的延遲信息,默認參數是1s。例如--max-lag=5 --check-interval=20
- 默認值是1s。在每個chunk拷貝完畢之後,都會去獲取所有slave的延遲信息(Seconds_Behind_Master),當延遲的值是大於設置的值的話,那麼會暫停複製,等待延遲的值小於這個設置的值。這個參數和
- --chunk-time
- 默認值是0.5s。定義每個chunk備份使用的最長耗時。會在線自己動態調整chunk-size的大小根據服務器的性能。
- 也可以通過另外一個選項--chunk-size禁止動態調整,即每次固定拷貝 1k 行,如果指定則默認1000行,且比 chunk-time 優先生效。
- --set-vars
- 可以在線修改參數設置,例如
SET SESSION innodb_lock_wait_timeout=1
,SET SESSION lock_wait_timeout=60
,SET SESSION wait_timeout=10000
。默認設置的wait_timeout是10000s,在進行DDL操作的時候必須考慮是否在這個時間內完成DDL操作,假如不能在這個默認的時間內完成DDL操作,則需要考慮將這個參數的值調大。
- 可以在線修改參數設置,例如
- --dry-run
- 創建和修改新表,但是不會嘗試創建觸發器,複製數據,替換舊錶。並不真正執行,可以看到生成的執行語句。建議和--print搭配使用。
- --execute
- 真正執行DDL操作。
pt-online-schema-change工作缺點
- 更容易導致主從數據延遲
- 如果運行過程中報錯了,無法從上一個位置繼續進行,需要從頭開始
- 不能存在觸發器
- MySQL中一個table中不能存在倆個類型一樣的觸發器。若原表中存在觸發器,那麼使用的過程中會報錯
- 外鍵約束
- 假如存在倆個表tb1和tb2,表tb2上面存在表tb1的外鍵。在alter table tb1的過程中最後rename階段由於tb2上面的外鍵約束檢查會導致rename失敗。
- pt-osc提供--alter-foreign-keys-method選項來決定怎麼處理這種情況:
- rebuild_constraints,優先採用這種方式:首先在表tb2上面drop掉外鍵,然後create新的外鍵指向_new_table;然後rename交換表名;最後drop舊錶。但是在這個過程中,假如表tb2過大,導致alter操作可能耗時過長,pt-osc會強制選擇drop_swap
- drop_swap:禁用tb2表外鍵約束檢查FOREIGN_KEY_CHECKS=0,然後drop掉原表,再rename新表。這種方式速度更快,也不會阻塞請求,但是還是存在一定的風險:drop原表的瞬間到rename過程,原表是不存在的,遇到請求會報錯;如果因爲BUG或者某些原因,舊錶已經刪除,新表rename失敗,那就太晚了。不過這種情況還是很少見的。
-
在使用之前需要對磁盤容量進行評估。
- 再ddl的過程中pt-osc是會完全複製一份新的數據的,還有就是這些操作是會記錄到binlog的。
- pt-osc是如何避免主從數據不一致的:在創建出發器的時候update舊錶,會觸發再新表的replace操作,然後再複製數據的時候使用的是insert ... ignore ...,其目的是爲了避免還沒有複製到修改的數據時候,再進行update操作會導致數據不一致。
- 例如時間t1和t2,並且t1是早於t2。在t1的時候update修改old_tabke的數據data,由於觸發器會觸發new_table的replace(replace操作是假如數據存在的話則替換,不存在的話則插入)操作。主要是因爲怕數據data還沒有複製到new_table,這個時候執行update操作的話肯定會報錯;還有一個原因就是在複製到data的時候,由於data是replace操作的,就是已經是插入的最新修改的值,這個時候使用select...ignore...的目的就是假如這個行數據存在的話那麼就不需要插入。
- table上面必須存在主鍵或者唯一索引。
- 不支持5.7的虛擬列功能
使用pt-osc還是online ddl的建議
- online ddl在必須copy table時成本較高,不宜採用
- pt-osc工具在存在觸發器時,不適用
- 修改索引、外鍵、列名時,優先採用online ddl,並指定 ALGORITHM=INPLACE
- 其它情況使用pt-osc,雖然存在copy data
- pt-osc比online ddl要慢一倍左右,因爲它是根據負載調整的
- 無論哪種方式都選擇的業務低峯期執行
- 特殊情況需要利用主從特性,先alter從庫,主備切換,再改原主庫
- 截圖percona
MySQL online DDL
online DDL
在 MySQL 5.1 (帶InnoDB Plugin)和5.5中,有個新特性叫 Fast Index Creation(下稱 FIC),就是在添加或者刪除二級索引的時候,可以不用複製原表。對於之前的版本對於索引的添加刪除這類DDL操作,MySQL數據庫的操作過程爲如下:
- 創建臨時表,更改表結構
- copy data
- 刪除原表
- rename 臨時表
在copy數據的過程中,原表全程鎖表只允許讀,如果有寫進入的話會將會無法提供服務,連接數會暴漲
Fast Index Creation (FIC)
引入FIC之後,創建二級索引,數據庫不在會重建表(rebulid table),而是在創建的過程中給表加上一個S鎖;刪除索引,只是需要更改內部視圖,並標記這個索引的空間可用,去掉數據庫該元數據上面索引的定義。這個過程也只允許讀操作,但是大大加快了索引的修改(不包含主鍵索引,因爲主索引的特性註定了它需要重建表)
但是在5.6之後,這個特性的範圍擴大了添加列,刪除列,列的重命名等。
online DDL會阻塞DDL操作
- 修改列的數據類型
- 更改表的字符集
- 指定字符集
- 創建全文索引
- 刪除主鍵
⚠️在刪除舊的主鍵並且添加新的主鍵的時候是不會阻塞DML的
online DDL不會阻塞DML
- 像其餘的添加列,刪除列,更改列名等都不會阻塞當前的DML
-
不阻塞的原理
- 在online DDL一些操作雖然有些操作不會rebuild table,類似於索引的刪除,添加,但是有寫操作也是需要rebuild table,類似於刪除列,添加列等
- rebuild table階段不阻塞在線DML的操作的原因是因爲在執行alter table這個事務之後的增量數據會寫倆份,一份是寫入原表,一份記錄在row_log。在copy data的時候,修改之後的數據是不會寫入臨時表中的,在copy data數據完成之後做row_log回放的時候,會和row_log裏面的版本號進行比對,假如當前版本號大於或者等於row_log記錄的版本號是不會在重做一次的。