pt-online-schema-change 最佳實踐(轉)


pt的詳細步驟

Step 1: Create the new table. Step 2: Alter the new, empty table. This should be very quick, or die if the user specified a bad alter statement. Step 3: Create the triggers to capture changes on the original table and apply them to the new table. Step 4: Copy rows. Step 5: Rename tables: orig -> old, new -> orig Step 6: Update foreign key constraints if there are child tables. Step 7: Drop the old table. DROP TABLE IF EXISTS `_xx_old` DROP TRIGGER IF EXISTS `pt_osc_xx_xx_del`; DROP TRIGGER IF EXISTS `pt_osc_xx_xx_upd`; DROP TRIGGER IF EXISTS `pt_osc_xx_xx_ins`; done 

一、常用參數解讀

1.0 生產環境使用的參數

inception調用pt-online-schema-change,相關參數如下: inception_osc_alter_foreign_keys_method = rebuild_constraints inception_osc_check_alter = on inception_osc_check_interval = 5 inception_osc_check_replication_filters = OFF inception_osc_chunk_size = 1000 inception_osc_chunk_size_limit = 4 inception_osc_chunk_time = 1 inception_osc_critical_thread_connected = 4000 inception_osc_critical_thread_running = 300 inception_osc_drop_new_table = on inception_osc_drop_old_table = on inception_osc_max_lag = 3 inception_osc_max_thread_connected = 2500 inception_osc_max_thread_running = 200 inception_osc_min_table_size = 16 inception_osc_recursion_method = none 以上inception參數對應的pt-online-schema-change的命令參數如下: pt-online-schema-change --alter " xx " --alter-foreign-keys-method=rebuild_constraints --check-alter=yes --check-interval=5 --check-replication-filters=no --chunk-size=1000 --chunk-size-limit=4 --chunk-time=1 --critical-load=thread_connected:4000,thread_running:300 --max-load=thread_connected:2500,thread_running:200 --drop-new-table=yes --drop-old-table=yes --max-lag=3 --recursion-method=none

1.1 基本用法

  • pt-online-schema-change [OPTIONS] DSN
  • pt-online-schema-change --alter "ADD COLUMN c1 INT" D=sakila,t=actor
  • pt-online-schema-change --alter "ENGINE=InnoDB" D=sakila,t=actor

1.2 安全的pt-online-schema-change

默認情況下,pt-online-schema-change 是不會修改表的,除非你顯示的指定了 --execute
pt-online-schema-change 有一系列動作來阻住一切不期望的后果發生,包括 自動檢測復制,以及以下相關措施

  • 大部分情況下,pt-online-schema-change會拒絕給沒有主鍵和唯一鍵的表做操作,可以參考 --alter 了解更多信息
  • 如果檢測到復制過濾(ignore-db,do-db等),pt-online-schema-change會拒絕操作,可以參考 --[no]check-replication-filters 了解更多信息
  • 如果發現復制嚴重的厲害,那么會暫停copy數據,可以參考 --max-lag 了解更多的信息
  • 如果發現服務器負載非常高,那么也會暫停或者停止相關操作,可以參考 --max-load and --critical-load 了解更多信息
  • 該工具默認會設置 innodb_lock_wait_timeout=1 和 lock_wait_timeout=60來減少競爭 , 參考 --set-vars 了解更多信息
  • 如果有外鍵約束,那么禁止改表,出發你指定 --alter-foreign-keys-method.
  • Percona XtraDB Cluster中禁止修改MYISAM的表

1.3 常用參數

  • --dry-run and --execute , 這兩個是互斥的參數,一個是打印,一個是執行
  • --alter

通過這個選項,就不需要alter table關鍵字了。 你可以通過逗號來指定多個修改操作。

* 以下列出--alter中的一些限制,大家謹記和避免

1. 原表必須要有主鍵或唯一鍵,因為delete觸發器需要用到,否則會報錯 2. rename子句,不允許給表重命名 2.1 不能通過刪除一列,然后再新增一列的方式來完成對列的重命名操作 3. 新增字段,如果這個字段是NOT NULL,必須要指定default值,否則報錯。 你必須指定默認值 4. 如果是DROP FOREIGN KEY constraint_name , 那么必須指定 _ 加上 constraint_name , 而不是 constraint_name。 舉例: CONSTRAINT `fk_foo` FOREIGN KEY (`foo_id`) REFERENCES `bar` (`foo_id`) 你必須指定: --alter "DROP FOREIGN KEY _fk_foo" 而不是 --alter "DROP FOREIGN KEY fk_foo". 5. 必須確保數據庫高於5.0版本,因為5.0版本轉換MYSIAM到InnoDB會出錯
  • [no]check-alter

默認yes, 給--alter 做一些檢測

* 列的重命名

在之前的版本 CHANGE COLUMN name new_name 這個操作是會丟失數據的,現在的工具修復了

但是,由於pt代碼並不是full-blown SQL parser,所以,你應該先 --dry-run and --print , 確認下renamed的列名是否正確,以確保無誤 * 刪除主鍵 刪除主鍵是很危險的事情,盡量不要做這樣的動作
  • --alter-foreign-keys-method

我們的規范不允許有外鍵,如果有外鍵,我們采取其他方式DDL

如何把外鍵引用到新表?需要特殊處理帶有外鍵約束的表,以保證它們可以應用到新表.當重命名表的時候,外鍵關系會帶到重命名后的表上。
該工具有兩種方法,可以自動找到子表,並修改約束關系。
    auto: 在rebuild_constraints和drop_swap兩種處理方式中選擇一個。
    rebuild_constraints:使用 ALTER TABLE語句先刪除外鍵約束,然后再添加.如果子表很大的話,會導致長時間的阻塞。 drop_swap: 執行FOREIGN_KEY_CHECKS=0,禁止外鍵約束,刪除原表,再重命名新表。這種方式很快,也不會產生阻塞,但是有風險: 1, 在刪除原表和重命名新表的短時間內,表是不存在的,程序會返回錯誤。 2, 如果重命名表出現錯誤,也不能回滾了.因為原表已經被刪除。 none: 類似"drop_swap"的處理方式,但是它不刪除原表,並且外鍵關系會隨着重命名轉到老表上面。 
  • --host=xxx --user=xxx --password=xxx
連接實例信息,縮寫-h xxx -u xxx -p xxx,密碼可以使用參數--ask-pass 手動輸入。 
  • D=db_name,t=table_name
指定要ddl的數據庫名和表名


  • --charset
最好設置為MySQL默認字符集: utf8
  • --check-interval
默認1秒,檢測--max-lag 
  • --[no]check-replication-filters

默認yes

如果發現任何服務器有 binlog_ignore_db and replicate_do_db , 那么就報錯 
  • --check-slave-lag
指定一個從庫的DSN連接地址,如果從庫超過--max-lag參數設置的值,就會暫停操作。
  • --[no]swap-tables
默認yes。交換原始表和新表,除非你禁止--[no]drop-old-table。
  • --max-lag
默認1s。
每個chunk拷貝完成后,會查看所有復制Slave的延遲情況。
要是延遲大於該值,則暫停復制數據,直到所有從的滯后小於這個值,使用Seconds_Behind_Master。
如果有任何從滯后超過此選項的值,則該工具將睡眠--check-interval指定的時間,再檢查。 如果從被停止,將會永遠等待,直到從開始同步,並且延遲小於該值。 如果指定--check-slave-lag,該工具只檢查該服務器的延遲,而不是所有服務器。 
  • --max-load
默認為Threads_running=25。
每個chunk拷貝完后,會檢查SHOW GLOBAL STATUS的內容,檢查指標是否超過了指定的閾值。 如果超過,則先暫停。 這里可以用逗號分隔,指定多個條件, 每個條件格式: status指標=MAX_VALUE 或者 status指標:MAX_VALUE。 如果不指定MAX_VALUE,那么工具會設置其為當前值的120%。 
  • --critical-load
默認為Threads_running=50。
用法基本與--max-load類似,如果不指定MAX_VALUE,那么工具會這只其為當前值的200%。 如果超過指定值,則工具直接退出,而不是暫停。
  • --print
打印SQL語句到標准輸出。指定此選項可以讓你看到該工具所執行的語句,和--dry-run配合最佳。
  • --progress
復制數據的時候打印進度報告,二部分組成:第一部分是百分比,第二部分是時間。
  • --set-vars
設置MySQL變量,多個用逗號分割。
默認該工具設置的是: wait_timeout=10000 innodb_lock_wait_timeout=1 lock_wait_timeout=60
  • --recursion-method

默認是show processlist,發現從的方法,也可以是host,但需要在從上指定report_host,通過show slave hosts來找到,可以指定none來不檢查Slave。 METHOD USES =========== ================== processlist SHOW PROCESSLIST hosts SHOW SLAVE HOSTS dsn=DSN DSNs from a table none Do not find slaves 指定none則表示不在乎從的延遲。 

--pause-file

可以指定文件暫停pt-online-schema-change 

二、使用限制

  • 哪些ddl是不可以做的,做了容易出錯
1. 禁止創建唯一索引,會丟失數據,更加不允許添加 --alter-check=no,--check-unique-key-change=no 2. 如果原表沒有主鍵,或者也沒有唯一索引,這些表是不允許用pt做DDL的 3. 禁止對外鍵的表進行pt ddl 4. 禁止對表進行重命名 5. 禁止對列進行重命名,如果一定要做,也必須先print出來檢測清楚列名是否正確 6. 新增字段,NOT NULL必須要指定默認值 7. 不允許刪除主鍵
  • 由於pt觸發器原理,rowcopy會產業一堆的binlog,所以做之前要檢測binlog空間是否夠用,也要檢測數據空間多一倍表空間是否夠用
  • 禁止在業務高峰期進行pt-online-schema-change操作
  • 原表不能有觸發器
  • MySQL最好設置為innodb_autoinc_lock_mode=2,否則在高並發的寫入情況下,很容易產生所等待以及死鎖
  • master的表結構必須跟slave的表結構一致,不允許異構,否則pt-online-schema-change的原理就是會rename,然后slave不一致的表結構會被master覆蓋,謹記

三、關於觸發器

  • 3.0.2之前的update觸發器
REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`, `c1`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`, NEW.`c1`)
  • 3.0.2之后的update觸發器
BEGIN DELETE IGNORE FROM `lc`.`_hb_new` WHERE !(OLD.`id` <=> NEW.`id`) AND `lc`.`_hb_new`.`id` <=> OLD.`id`; REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`); END 
  • 原理
update觸發器 =SQL轉換=> delete ignore + replace into (大於3.0.2版本) =SQL轉換=> replace into(低於3.0.2版本,所以這個版本會有問題,如果這時候對老的主鍵修改,那么修改之前的值不會去掉,從而多了一些異常數據) 舉例:t表中有三條數據,第一列id是主鍵 ------ 1 lc --row1 2 lc --row2 3 lc --row3 ------ pt-online-schema-change的原理大致四個階段: 1. 創建臨時表_t_new 2. 創建觸發器 3. 老數據row copy 4. swap table 好了,我們來舉個例子: 1. 創建臨時表_t_new 2. 創建觸發器 3. 老數據row copy 3.1 拷貝數據row1,row2完畢 3.2 這時候業務有一個update語句, update t set id = 10 where id=1; 3.3 拷貝數據row3 4. swap table 這時候腦補一下原表和新表的示意圖, 這時候已經執行到3.1階段 老表 ------------ 1 lc --row1 2 lc --row2 3 lc --row3 ------------ 新表 ----------- 1 lc 2 lc ----------- 這時候腦補一下原表和新表的示意圖, 這時候已經執行到3.3階段 老表(update t set id = 10 where id=1) ------------ 10 lc --row1 2 lc --row2 3 lc --row3 ------------ 新表(3.0.2之前版本的觸發器,沒有delete映射,所以最終結果如下,跟老表相比已經不一致了,多了一條數據1,lc) , 觸發器 replace into _t_new(id,name) values(10,lc) ----------- 1 lc 2 lc 10 lc 3 lc ----------- 新表(3.0.2之后版本的觸發器,有delete映射,所以最終結果如下,於老表的數據一致) , 觸發器 delete ignore _t_new where id = 1;replace into _t_new(id,name) values(10,lc); ----------- 2 lc 10 lc 3 lc ----------- 

四、錯誤處理

遇到錯誤后,繼續補充完整


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM