pt-osc修改外鍵內部是如何處理的?

在講解pt-osc內部處理流程前,我們先通過下面的例子,看看rename交換表後,子表的信息。

-- 創建一個父表
CREATE TABLE parent (
id int(11) NOT NULL auto_increment,
parent_id int,
PRIMARY KEY  (id),
KEY IX_parent_id (parent_id)
) ENGINE=InnoDB;

-- 創建一個子表,外鍵是child_id,和父表parent_id做關聯
CREATE TABLE child (
id int(11) NOT NULL auto_increment,
child_id int(11) default NULL,
PRIMARY KEY  (id),
KEY IX_child_id (child_id),
FOREIGN KEY (child_id) REFERENCES parent (parent_id)
) ENGINE=InnoDB;

-- 把父表改個名
rename table parent to parent_1;

此時子表會自動執向新的父表表名,如下面所示:

show create table child\G

CREATE TABLE child (
  id int(11) NOT NULL AUTO_INCREMENT,
   child_id int(11) DEFAULT NULL,
  PRIMARY KEY (id),
  KEYI IX_child_id (child_id),
  CONSTRAINT child_ibfk_1 FOREIGN KEY (child_id) REFERENCES parent_1 (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


現在我們要向父表添加一個字段name varchar(200)

用pt-osc工具執行,通常內部的執行過程是:

1)創建一個臨時表_parent_new
2)在臨時表_parent_new中添加name字段
3)在原表parent上定義觸發器,以便對原始表上的數據所做的更改也將應用於臨時表_parent_new中
4)將數據從原表parent複製到_parent_new。
5)交換名字rename table parent to _parent_old, _parent_new to parent 

6)刪除原表 drop table _parent_old

7)刪除增刪改三個觸發器


那麼最危險的是rename交換名字後,子表的外鍵會執向_parent_old,並不會變成parent,這將帶來數據不一致的後果。


固,pt-osc增加了--alter-foreign-keys-method參數,默認是drop_swap,它的執行過程跟剛纔就有些區別了。

前4步還是一樣,第5步開始,變成

5)set FOREIGN_KEY_CHECKS=OFF; #關閉外鍵檢查

6)交換名字rename table parent to _parent_old

7)drop table _parent_old

8)交換名字 rename table _parent_new to _parent_old, _parent_old to parent;

9)刪除增刪改三個觸發器

10)set FOREIGN_KEY_CHECKS=ON;

第7步如果表大,刪除的速度較慢的話(第8步不會執行),業務會受影響,這也是比較危險的。


如果修改爲rebuild_constraints,它的執行過程是:

交換名字

rename table parent to _parent_old, _parent_new to parent

(這一步保持和原先一樣)

1)將子表外鍵刪除,重新關聯父表parent

ALTER TABLE child DROP FOREIGN KEY child_id, ADD CONSTRAINT child_ibfk_1 FOREIGN KEY  (child_id) REFERENCES parent (parent_id)

注:這一步會採用ALGORITHM=INPLACE算法,不會鎖表,支持併發DML。

2)刪除原表 drop table _parent_old

3)刪除增刪改三個觸發器


設置爲auto,如果子表中的行數很少,則使用rebuild_constraints; 否則轉換爲drop_swap。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章