OSC 在線更改表結構

隨着業務的發展,更改表結構變的越來越常見。一般情況下,我們通過alter table 之類的DDL語句就可以完成。然而當執行alter table 語句時,數據庫會對整個實例加鎖,阻塞業務的所有操作,當線上數據表數據量非常龐大時,阻塞時間將會非常長,這對於我們是無法容忍的。因此我們不能簡單粗暴地對原表執行alter table語句。

一、OSC操作

在線更改表結構有兩種方法:

1、主從切換。即先逐步下線從庫,在從庫上執行alter table 語句,完成後替換線上從庫,這樣一臺一臺修改,最後做一下主從切換,再進行一次結構修改。整個過程耗時很長,並且做主從切換時,風險也很大。

2、Online Scheme Change,即OSC。



簡單地來講,OSC實際上是建立一張新表,在新表上執行DDL操作,然後將原表的數據同步到新表中,最後把新表rename爲原表,並將原表刪除或備份。在數據的同步中,除了要複製原始數據,也要將操作過程中原表數據產生的變化進行記錄,以保證數據一致性,可以採用觸發器記錄更改。

整個OSC過程可以分爲幾個階段:

1、創建新表。

2、創建觸發器。

3、複製數據。

4、重放記錄。

5、重命名(rename)。

6、清理。

下面分別介紹這幾個階段。

1、創建新表。在dba的實際操作中,往往需要在開發機上寫出最終的表結構創建語句,然後通過ftp供dba下載操作。

2、創建觸發器。可以設置mysql的insert、update和delete觸發器,將更改保存到delta表中。delta表設計如下:



delta表保存了自增字段,更新類型(插入、更新、刪除),是否已經被重放這三個字段以及原表的所有字段。

觸發器觸發時,可以通過old和new關鍵字將更新之後的數據存儲到delta表中,供重放使用。

創建觸發器的代碼如下:

(1)插入觸發器

delta表中存儲插入的數據

(2)刪除觸發器

delta表中存儲刪除的數據

(3)更新觸發器

delta表中存儲的是更新之前的數據,更新之後的數據直接從原表獲取即可(避免同一條記錄被多次更新)

3、複製數據

將表數據從A導到B有好幾種方法,最常用的一種是insert into B select * from A,在執行該語句時,數據庫select的結果集加鎖,影響業務,因此我們不能採用這種方案。

實際上,我們可以使用select...into outfile和load data infile的組合來實現,這樣是不會對紀錄進行鎖定的。考慮到一個表的數據量可能很大,可以根據select limit 分批次導出數據,如下所示:

注意:導入導出數據需要有file權限,此外,路徑設置還需要考慮是否設置@@secure_file_priv變量。

4、重放記錄

從delta表中查詢所有未被重放的,對於插入類型,執行插入操作;刪除類型,執行刪除操作;更新類型,更新的最終值從原表獲取,條件從delta表中獲取。

注意,重放記錄至少需要執行兩次,第一次,在複製完數據完成之後;第二次,在rename之前,以保證數據一致性。

5、重命名

操作完成後,通過mysql的rename命令,將新表重命名爲原表,原表命名爲備份表。注意,rename是一個原子操作,需要將兩次重命名寫到一條命令裏。

6、清理

OSC操作完成後,將產生的備份表、觸發器、delta表等刪掉,以免影響下次使用。

二、總結

以上即爲OSC的全部過程,可以看出,精華就在於觸發器那一部分的使用,由於工具的複雜性,使用中還有一些注意事項:

1、此工具不是原子操作,如果某一點失敗,處理不好,會留下很多中間過程的垃圾文件,這些可能會影響下次OSC操作;

2、執行OSC操作的原表和新表不能更改字段順序,切記切記!

3、在執行之前,要對磁盤容量進行評估,因爲OSC會使用表一倍以上的空間。

4、表不能有外鍵,否則可能會出現意想不到的問題。

源自小哥:司馬迪

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