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、經常使用參數解讀

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 有一系列動做來阻住一切不指望的後果發生,包括 自動檢測複製,以及如下相關措施javascript

  • 大部分狀況下,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關鍵字了。 你能夠經過逗號來指定多個修改操做。java

* 如下列出--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 作一些檢測python

* 列的重命名

在以前的版本 CHANGE COLUMN name new_name 這個操做是會丟失數據的,如今的工具修復了

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

咱們的規範不容許有外鍵,若是有外鍵,咱們採起其餘方式DDLsql

如何把外鍵引用到新表?須要特殊處理帶有外鍵約束的表,以保證它們能夠應用到新表.當重命名錶的時候,外鍵關係會帶到重命名後的表上。
該工具備兩種方法,能夠自動找到子表,並修改約束關係。
    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 

2、使用限制

  • 哪些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、關於觸發器

  • 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 ----------- 

4、錯誤處理

遇到錯誤後,繼續補充完整bash

相關文章
相關標籤/搜索