使用 pt-online-schema-change 實現在線DDL
問題背景
平時進行修改表的結構,更改字段,新增字段,更改字段名稱一般都是通過ALTER TABLE 語法進行修改的。對於小表或者並發訪問不是很大的情況是OK。但是如果是在線大表,那就很麻煩。由於表數據量大,復制表需要比較長的時間,在這個時間段裏面,表是被加了鎖的(寫鎖),加寫鎖時其他用戶只能select表不能update、insert表。表數據量越大,耗時越長。
mysql在線ddl(加字段、加索引等修改表結構之類的操作)過程如下:
- 對表加鎖(表此時只讀)
- 復制原表物理結構
- 修改表的物理結構
- 把原表數據導入中間表中,數據同步完後,鎖定中間表,並刪除原表
- rename中間表為原表
- 刷新數據字典,並釋放鎖
可見,在這個過程中會鎖表。造成當前操作的表無法寫入數據,影響用戶使用。由於需要復制原表的數據到中間表,所以表的數據量越大,等待的時候越長,卡死在那裏(用戶被拒絕執行update和insert操作,表現就是延遲了一直在等待)。
對於DDL操作一個基本的想法:它的變化是就地執行還是執行表拷貝, 在命令結束之後看看顯示“rows affected “的值。例如,這裏您可能會看到在做不同類型的DDL操作: 修改列默認值(超級快,不影響表的所有數據): Query OK, 0 rows affected (0.07 sec) 添加索引 (需要時間, 但0 rows affected 表明表沒有被復制): Query OK, 0 rows affected (21.42 sec) 改變列的數據類型(需要大量的時間和需要重建表中的所有行): Query OK, 1671168 rows affected (1 min 35.54 sec) 例如, 在一個大表運行一個DDL操作之前,你可能會檢查操作是將快還是慢,如下所示: 克隆表結構。 用少量數據填充克隆的表。 在克隆的表運行DDL操作。 檢查 “行受影響”的值是否為零或不是。一個非零值意味著操作需要重建整個表,這可能需要特殊的規劃。例如,你可能在計劃停機期間做DDL操作,或在復制每個從服務器。
解決方案
percona 的 pt-online-schema-change 工具原理:
1、如果存在外鍵,根據alter-foreign-keys-method參數的值,檢測外鍵相關的表,做相應設置的處理。
2、創建一個新的表,表結構為修改後的數據表,用於從源數據表向新表中導入數據。
3、創建觸發器,用於記錄從拷貝數據開始之後,對源數據表繼續進行數據修改的操作記錄下來,用於數據拷貝結束後,執行這些操作,保證數據不會丟失。
4、拷貝數據,從源數據表中拷貝數據到新表中。
5、修改外鍵相關的子表,根據修改後的數據,修改外鍵關聯的子表。
6、rename源數據表為old表,把新表rename為源表名,並將old表刪除。
7、刪除觸發器。
可見,復制表的時候無需加鎖,不影響原表繼續接受寫請求;
使用 pt-online-schema-change 實現在線DDL