pt-osc(pt-online-schema-change)工具實現原理剖析
使用方法:
pt-online-schema-change h=*,u=* p=**,P=* ,D=enk,t=my1 --alter"add is_sign_1 int(11) unsigned NOT NULL DEFAULT '0'"--drop-old-table [--sleep10]
pt-online-schema-change線上更改表結構的實現核心有如下幾個過程:
(注:在跟改過程中涉及到三個表:原表、tmp_table即作為原表導資料的臨時表,old_table在最後rename 原表的結果表)
1、
CREATE TABLE `$db`.`$tmp_tbl` LIKE`$db`.`$tbl`"
新建tmp_table,表結構同原表
2、
在tmp_table上更改表結構為需要的表結構
3、
在原表上建立三個觸發器,如下:
(1)CREATETRIGGER mk_osc_del AFTER DELETE ON $table " "FOR EACH ROW "
"DELETE IGNORE FROM $new_table ""WHERE$new_table.$chunk_column = OLD.$chunk_column";
(2)CREATETRIGGER mk_osc_ins AFTER INSERT ON $table " "FOR EACH ROW "
"REPLACEINTO $new_table ($columns) "
"VALUES($new_values)";
(3)CREATETRIGGER mk_osc_upd AFTER UPDATE ON $table " "FOR EACH ROW "
"REPLACE INTO $new_table ($columns) ""VALUES ($new_values)";
我們可以看到這三個觸發器分別對應於INSERT、UPDATE、DELETE三種操作,
(1)
mk_osc_del,DELETE操作,我們注意到DELETEIGNORE,當新有資料時,我們才進行操作,也就是說,當在後續匯入過程中,如果刪除的這個資料還未匯入到新表,那麼我們可以不在新表執行操作,因為在以後的匯入過程中,原表中改行資料已經被刪除,已經沒有資料,那麼他也就不會匯入到新表中;
(2)
mk_osc_ins,INSERT操作,所有的INSERT INTO全部轉換為REPLACEINTO,為了確保資料的一致性,當有新資料插入到原表時,如果觸發器還未把原表資料未同步到新表,這條資料已經被匯入到新表了,那麼我們就可以利用replaceinto進行覆蓋,這樣資料也是一致的
(3)
mk_osc_upd
UPDATE操作,所有的UPDATE也轉換為REPLACEINTO,因為當跟新的資料的行還未同步到新表時,新表是不存在這條記錄的,那麼我們就只能插入該條資料,如果已經同步到新表了,那麼也可以進行覆蓋插入,所有資料與原表也是一致的;
我們也能看出上述的精髓也就這這幾條replaceinto操作,正是因為這幾條replaceinto才能保證資料的一致性
4、
複製原表資料到臨時表中,在指令碼中使用如下語句
INSERT IGNORE INTO $to_table ($columns) "
"SELECT $columns FROM $from_table ""WHERE ($chunks->[$chunkno])",我們能看到他是透過一些查詢(基本為主鍵、唯一鍵值)分批把資料匯入到新的表中,在匯入前,我們能透過引數--chunk-size對每次匯入行數進行控制,已減少對原表的鎖定時間,並且在匯入時,我們能透過—sleep引數控制,在每個chunk匯入後與下一次chunk匯入開始前sleep一會,sleep時間越長,對於磁碟IO的衝擊就越小
5、
Rename 原表到old表中,在把臨時表Rename為原表,
"RENAME TABLE `$db`.`$tmp_tbl`TO `$db`.`$tbl`"; 在rename過程,其實我們還是會導致寫入讀取堵塞的,所以從嚴格意思上說,我們的OSC也不是對線上環境沒有一點影響,但由於rename操作只是一個修改名字的過程,也只會修改一些表的資訊,基本是瞬間結束,故對線上影響不太大
6、
清理以上過程中的不再使用的資料,如OLD表
以上即為整個Percona OSC的過程,我們看到精華部分就觸發器那一塊,不過還有很多細節我未介紹,如:外來鍵、記錄binlog(預設情況是不記錄binlog的)等等,由於環境的複雜性,此工具還是有很多風險,如以下幾個方面問題或者需要規避的一些問題:
1、
此工具不是原子操作,如果某一點失敗,不僅僅會留下很多中間過程的垃圾檔案,而這些檔案很難完全清理,並且如果有這些檔案存在,那麼就不能在次執行OSC操作;
2、
在執行時,儘量避免有這個表的批次更新、鎖表、最佳化表的操作,我們能想象的到,如果有鎖表、最佳化表那麼OSC是否還能正常執行?
3、
如果存在主從結構,那麼儘量在從庫先執行,因為如果在主庫執行完畢後在到從庫執行,我們能想象,主庫欄位多同步到從庫,會不會有問題呢?
4、
必須是單一列的主鍵或者單一唯一鍵,這樣我們在insert select *from分片時,是不是能更好的處理量呢?
5、
不要有外來鍵,儘管指令碼經過嚴格測試,但是是否還有bug,也未知,表的外來鍵是不是會帶來更多的問題呢?
6、
在執行之前,我們是不是要對磁碟容量進行評估呢?因為OSC會使用表的一倍以上空間。
pt-online-schema-change h=*,u=* p=**,P=* ,D=enk,t=my1 --alter"add is_sign_1 int(11) unsigned NOT NULL DEFAULT '0'"--drop-old-table [--sleep10]
pt-online-schema-change線上更改表結構的實現核心有如下幾個過程:
(注:在跟改過程中涉及到三個表:原表、tmp_table即作為原表導資料的臨時表,old_table在最後rename 原表的結果表)
1、
CREATE TABLE `$db`.`$tmp_tbl` LIKE`$db`.`$tbl`"
新建tmp_table,表結構同原表
2、
在tmp_table上更改表結構為需要的表結構
3、
在原表上建立三個觸發器,如下:
(1)CREATETRIGGER mk_osc_del AFTER DELETE ON $table " "FOR EACH ROW "
"DELETE IGNORE FROM $new_table ""WHERE$new_table.$chunk_column = OLD.$chunk_column";
(2)CREATETRIGGER mk_osc_ins AFTER INSERT ON $table " "FOR EACH ROW "
"REPLACEINTO $new_table ($columns) "
"VALUES($new_values)";
(3)CREATETRIGGER mk_osc_upd AFTER UPDATE ON $table " "FOR EACH ROW "
"REPLACE INTO $new_table ($columns) ""VALUES ($new_values)";
我們可以看到這三個觸發器分別對應於INSERT、UPDATE、DELETE三種操作,
(1)
mk_osc_del,DELETE操作,我們注意到DELETEIGNORE,當新有資料時,我們才進行操作,也就是說,當在後續匯入過程中,如果刪除的這個資料還未匯入到新表,那麼我們可以不在新表執行操作,因為在以後的匯入過程中,原表中改行資料已經被刪除,已經沒有資料,那麼他也就不會匯入到新表中;
(2)
mk_osc_ins,INSERT操作,所有的INSERT INTO全部轉換為REPLACEINTO,為了確保資料的一致性,當有新資料插入到原表時,如果觸發器還未把原表資料未同步到新表,這條資料已經被匯入到新表了,那麼我們就可以利用replaceinto進行覆蓋,這樣資料也是一致的
(3)
mk_osc_upd
UPDATE操作,所有的UPDATE也轉換為REPLACEINTO,因為當跟新的資料的行還未同步到新表時,新表是不存在這條記錄的,那麼我們就只能插入該條資料,如果已經同步到新表了,那麼也可以進行覆蓋插入,所有資料與原表也是一致的;
我們也能看出上述的精髓也就這這幾條replaceinto操作,正是因為這幾條replaceinto才能保證資料的一致性
4、
複製原表資料到臨時表中,在指令碼中使用如下語句
INSERT IGNORE INTO $to_table ($columns) "
"SELECT $columns FROM $from_table ""WHERE ($chunks->[$chunkno])",我們能看到他是透過一些查詢(基本為主鍵、唯一鍵值)分批把資料匯入到新的表中,在匯入前,我們能透過引數--chunk-size對每次匯入行數進行控制,已減少對原表的鎖定時間,並且在匯入時,我們能透過—sleep引數控制,在每個chunk匯入後與下一次chunk匯入開始前sleep一會,sleep時間越長,對於磁碟IO的衝擊就越小
5、
Rename 原表到old表中,在把臨時表Rename為原表,
"RENAME TABLE `$db`.`$tmp_tbl`TO `$db`.`$tbl`"; 在rename過程,其實我們還是會導致寫入讀取堵塞的,所以從嚴格意思上說,我們的OSC也不是對線上環境沒有一點影響,但由於rename操作只是一個修改名字的過程,也只會修改一些表的資訊,基本是瞬間結束,故對線上影響不太大
6、
清理以上過程中的不再使用的資料,如OLD表
以上即為整個Percona OSC的過程,我們看到精華部分就觸發器那一塊,不過還有很多細節我未介紹,如:外來鍵、記錄binlog(預設情況是不記錄binlog的)等等,由於環境的複雜性,此工具還是有很多風險,如以下幾個方面問題或者需要規避的一些問題:
1、
此工具不是原子操作,如果某一點失敗,不僅僅會留下很多中間過程的垃圾檔案,而這些檔案很難完全清理,並且如果有這些檔案存在,那麼就不能在次執行OSC操作;
2、
在執行時,儘量避免有這個表的批次更新、鎖表、最佳化表的操作,我們能想象的到,如果有鎖表、最佳化表那麼OSC是否還能正常執行?
3、
如果存在主從結構,那麼儘量在從庫先執行,因為如果在主庫執行完畢後在到從庫執行,我們能想象,主庫欄位多同步到從庫,會不會有問題呢?
4、
必須是單一列的主鍵或者單一唯一鍵,這樣我們在insert select *from分片時,是不是能更好的處理量呢?
5、
不要有外來鍵,儘管指令碼經過嚴格測試,但是是否還有bug,也未知,表的外來鍵是不是會帶來更多的問題呢?
6、
在執行之前,我們是不是要對磁碟容量進行評估呢?因為OSC會使用表的一倍以上空間。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15498/viewspace-2144372/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- RunTime實現原理剖析
- ARouter原理剖析及手動實現
- MySQL修改大表工具pt-online-schema-change原理MySql
- Android RollBack機制實現原理剖析Android
- 剖析Vue原理&實現雙向繫結MVVMVueMVVM
- 深入剖析 Laravel 服務提供者實現原理Laravel
- MVVM模式到底是什麼?實現原理剖析MVVM模式
- Spring原始碼剖析7:AOP實現原理詳解Spring原始碼
- 剖析漢字描紅在flutter中的實現原理Flutter
- Java執行緒池ThreadPoolExecutor實現原理剖析 #28Java執行緒thread
- Laravel 核心--深入剖析 Laravel 框架 Jwt 元件的實現原理Laravel框架JWT元件
- 外掛化實現Android多主題功能原理剖析Android
- pt-osc工具的優缺點歸納總結
- 值得收藏 | 深度剖析 TensorCore 卷積運算元實現原理卷積
- 深度剖析Spring Boot自動裝配機制實現原理Spring Boot
- pt-online-schema-change 工具使用薦
- Memcached 原理剖析
- Eureka原理剖析
- AbstractQueuedSynchronizer原理剖析
- JVM原理剖析JVM
- KVC原理剖析
- Java阻塞佇列中的異類,SynchronousQueue底層實現原理剖析Java佇列
- 百億級日誌流分析實踐 | 剖析個推後效分析功能實現原理
- 併發程式設計之 原始碼剖析 執行緒池 實現原理程式設計原始碼執行緒
- Openmp Runtime 庫函式彙總(下)——深入剖析鎖?原理與實現函式
- [java]HashMap原理剖析JavaHashMap
- ReactDom render原理剖析React
- Module Federation原理剖析
- Java CAS 原理剖析Java
- MySQL:pt-online-schema-change原理及注意點(未完)MySql
- Java物件複製原理剖析及最佳實踐Java物件
- 深入剖析Linux IO原理和幾種零拷貝機制的實現Linux
- Tinyalsa PCM API 實現深度剖析API
- pt-online-schema-change的操作原理簡單介紹
- 剖析 Elasticsearch 的索引原理Elasticsearch索引
- HashMap原理底層剖析HashMap
- Docker 原理剖析(三)rootfsDocker
- Kafka事務原理剖析Kafka