背景:
工作上需要刪除或則歸檔一張大表,這時候用pt-archiver可以很好的滿足要求,其不僅可以歸檔數據,還有刪除、導出到文件等功能。並且在主從架構當中,可以兼顧從庫(一個或則多個)進行歸檔,避免歸檔、刪除數據時候壓力太大,造成從庫的延遲。該工具的目標是一個低影響,從表中剔除舊數據,而不會影響OLTP查詢。也可以將數據插入到另一個表中,該表不必位於同一服務器上。
使用方法:
pt-archiver [OPTIONS] --source DSN --where WHERE
1)將所有行從oltp_server歸檔到olap_server並歸檔到文件:
pt-archiver --source h=oltp_server,D=test,t=tbl --dest h=olap_server \ --file '/var/log/archive/%Y-%m-%d-%D.%t' \ --where "1=1" --limit 1000 --commit-each
2)從子表中刪除行:
pt-archiver --source h=host,D=db,t=child --purge \ --where 'NOT EXISTS(SELECT * FROM parent WHERE col=child.col)'
參數說明:注意:至少需要指定--dest,--file,--purge 其中的一個。
1:--source :指定要歸檔表的信息,兼容DSN選項。
a:執行查詢時要使用的數據庫。 b:如果為true,則使用SQL_LOG_BIN禁用binlog。 h:連接的MySQL主機名或IP地址。 D:連接時使用的默認數據庫,可以在運行時使用不同的數據庫。 t:要被歸檔、刪除、導出的表。 i:進行歸檔、刪除、導出時,被指定使用的索引。 p:連接時使用的MySQL密碼。 P:連接時使用的MySQL端口。 S:用於連接的MySQL套接字文件(在Unix系統上)。 u:連接時使用的MySQL用戶名。 L:啟用LOAD DATA LOCAL INFILE。 A:連接MySQL的默認字符集(SET NAMES)。 F:通過配置文件讀取用戶名和密碼,如配置了〜/ .my.cnf,就會自動連接工具而無需用戶名或密碼。格式為: [client] user=your_user_name pass=secret
此項指定一個表,pt-archiver將在其中插入從--source歸檔的行。 它使用與--source相同的參數格式。 大多數缺失值默認為與--source相同的值,因此不必重復--source和--dest中相同的選項。如果--source和--dest的用戶名密碼不一樣,需要單獨各自指定,並且注意F和S參數。
3:--analyze:在--source或--dest上運行ANALYZE TABLE。字母's',將分析來源。 如果它包含'd',則將分析目的地。 您可以指定其中一個或兩個
--analyze=ds
4:--ascend-first:升序索引優化,提供最左索引(多列主鍵)的升序。
5:--no-ascend: 不要使用升序索引優化。注意多列主鍵索引。
6:--ask-pass:連接MySQL時提示輸入密碼。
7:--buffer:緩沖區輸出到--file並在提交時刷新,每次事務提交禁止刷寫到磁盤,有操作系統決定刷寫。該參數可以提高刷寫到文件的性能,但崩潰可能會有數據丟失。
8:--commit-each:控制事務大小,每次提取、歸檔就提交。禁用--txn-size。
9:--config:以逗號分隔的配置文件列表; 如果指定,則必須是命令行上的第一個選項。
10:--database:D,連接時使用的默認數據庫。
11:--delayed-insert:在insert后面添加delayed,延遲寫入。
12:--dry-run:打印查詢並退出而不做任何事情。
13:--file:要歸檔到的文件,使用以SELECT INTO OUTFILE相同的格式。如:--file '/var/log/archive/%Y-%m-%d-%D.%t'
%d Day of the month, numeric (01..31) %H Hour (00..23) %i Minutes, numeric (00..59) %m Month, numeric (01..12) %s Seconds (00..59) %Y Year, numeric, four digits %D Database name %t Table name
14:--for-update:在每個select語句后面加入for update。
15:--header:在--file頂部打印列標題。如果文件存在,不寫,可以用LOAD DATA INFILE保存文件。
16:--high-priority-select:在每個select語句上加入HIGH_PRIORITY。
17:--host:連接的MySQL地址。
18:--ignore:insert語句加入ignore。
19:--local:添加NO_WRITE_TO_BINLOG參數,OPTIMIZE 和 ANALYZE不寫binlog。
20:--low-priority-delete:每個delete語句加入LOW_PRIORITY。
21:--low-priority-insert:每隔insert和replace語句加入LOW_PRIORITY。
22:--max-lag:默認1s,由--check-slave-lag給出的從延遲。獲取行時查看從庫,如果slave的延遲大於選項的值,或者slave沒有運行(因此它的滯后為NULL),則pt-table-checksum會休眠--check-interval seconds,然后再次查看滯后。 它會一直重復,直到slave小於該參數,然后繼續獲取並歸檔該行。
23:--no-delete:不要刪除存檔的行,默認會刪除。不允許--no-ascend,因為啟用它們都會導致無限循環。
24:--optimize:在--source或--dest上運行之后OPTIMIZE TABLE。
25:--output-format:與--file一起使用以指定輸出格式,格式相當於FIELDS TERMINATED BY','OPTIONALLY ENCLOSED BY'''。
26:--password:-p,連接MySQL時使用的密碼。 如果密碼包含逗號,則必須使用反斜杠進行轉義。
27:--pid:創建給定的PID文件。 如果PID文件已存在並且其包含的PID與當前PID不同,則該工具將不會啟動。 但是,如果PID文件存在且其包含的PID不再運行,則該工具將使用當前PID覆蓋PID文件。 退出工具時會自動刪除PID文件。
28:--port:-P,連接MySQL時的端口。
29:--primary-key-only:僅限主鍵列。用於指定具有主鍵列的--columns的快捷方式,當DELETE語句只需要主鍵列時,它可以避免獲取整行。
30:--progress:每多少行打印進度信息:打印當前時間,已用時間以及每X行存檔的行數。
31:--purge:清除而不是歸檔; 允許省略--file和--dest。如果只想清除行,請考慮使用--primary-key-only指定表的主鍵列。 這樣可以防止無緣無故地從服務器獲取所有列。
32:--quick-delete:delete語句里添加quick。
33:--quite:-q,不打印任何輸出,包括--statistics的輸出,對--why-quit的輸出無效。
34:--replace:replace into代替insert into。
35:--retries:每次超時或死鎖的重試次數,默認1。
36:--run-time:退出前的時間。可選后綴s =秒,m =分鍾,h =小時,d =天; 默認s
37:--[no]safe-auto-increment:不要使用最大AUTO_INCREMENT歸檔行,默認yes。防止在服務器重新啟動時重新使用AUTO_INCREMENT值。
38:--sentinel:優雅的退出操作。指定的文件的存在將導致pt-archiver停止存檔並退出。 默認值為/tmp/pt-archiver-sentinel。
39:--slave-user:連接從庫的用戶。用戶必須存在於所有從屬服務器上
40:--slave-password:連接從庫的密碼。用戶的密碼在所有從站上必須相同。
41:--set-vars:逗號分隔的variable = value對列表中設置MySQL變量。如:--set-vars wait_timeout = 500
42:--share-lock:在SELECT語句里添加LOCK IN SHARE MODE。
43:--skip-foreign-key-checks:使用SET FOREIGN_KEY_CHECKS = 0禁用外鍵檢查。
44:--sleep:指定SELECT語句之間的休眠時間。 默認不sleep。 未提交事務,並且在休眠之前不會刷新--file文件。如果指定了--commit-each,則在休眠之前發生提交和刷新。
45:--sleep-coef:pt-archiver將在最后一次SELECT乘以指定系數的查詢時間內休眠。在每個SELECT之間休眠不同的時間,具體取決於SELECT所花費的時間。
46:--socket:-S,用於連接的套接字文件。
47:--statistics:收集並打印時間統計信息。
Started at 2008-07-18T07:18:53, ended at 2008-07-18T07:18:53 Source: D=db,t=table SELECT 4 INSERT 4 DELETE 4 Action Count Time Pct commit 10 0.1079 88.27 select 5 0.0047 3.87 deleting 4 0.0028 2.29 inserting 4 0.0028 2.28 other 0 0.0040 3.29 前兩行(或三行)顯示時間以及源表和目標表。接下來的三行顯示了提取,插入和刪除的行數。 其余行顯示計數和時間。列是操作,操作計時的總次數,花費的總時間以及程序總運行時間的百分比。行按照總時間下降的順序排序。最后一行是剩余的時間沒有明確歸因於任何東西。操作將根據命令行選項而有所不同。 如果給出了--why-quit,它的行為會略有改變。此選項使其打印退出的原因,即使只是因為沒有更多的行。
48:--stop:通過創建sentinel文件停止運行實例。
49:--txn-size:每個事務的行數,默認1。指定每個事務的大小(行數)。0完全禁用事務。在pt-archiver處理這么多行之后,如果指定該參數,它會提交--source和--dest,並刷新--file給出的文件。
此參數對性能至關重要。如果要從實時服務器(例如正在執行大量OLTP工作)進行存檔,則需要在事務大小和提交開銷之間選擇良好的平衡。較大的事務會產生更多的鎖爭用和死鎖,但較小的事務會導致更頻繁的提交開銷,如果沒有從事務存儲引擎進行歸檔,則可能需要禁用事務。
50:--user:-u,連接MySQL時的用戶。
51:--version:查看版本號。
52:--[no]version-check:不檢查版本號,默認yes。適用於RDS。
53:--where:指定WHERE子句以限制存檔的行。 子句里不要包含單詞WHERE,不需要WHERE子句,請使用--where 1=1。如:
--where 'ts < current_date - interval 90 day'
54:--limit:限制檢索要歸檔的行的SELECT語句返回的行數,默認是1。這可能會導致與其他查詢的更多爭用,具體取決於存儲引擎,事務隔離級別和--for-update等選項。
55:--bulk-delete:使用單個DELETE語句批量刪除每個行塊。該語句刪除塊的第一行和最后一行之間的每一行,隱含--commit-each。
56:--[no]bulk-delete-limit:添加--limit到--bulk-delete語句,默認yes。
57:--bulk-insert:使用LOAD DATA LOCAL INFILE插入每個行塊。 比使用INSERT語句一次插入行快得多。 通過為每個行塊創建一個臨時文件,並將行寫入此文件而不是插入它來實現的。此選項會強制使用批量刪除。
58:--charset:-A,設置默認字符集。
59:--[no]check-charset:不檢查字符集, 禁用此檢查可能會導致文本被錯誤地從一個字符集轉換為另一個字符集。進行字符集轉換時,禁用此檢查可能有用。
60:--[no]check-columns:檢查--source和--dest具有相同的列,默認yes。它不檢查列順序,數據類型等。它只檢查源中的所有列是否存在於目標中。存在差異則退出。不檢查則用參數–no-check-columns。
61:--columns:指定歸檔的列,以逗號分隔的列的列表以獲取寫入文件並插入目標表。 如果指定,將忽略其他列,除非它需要將它們添加到SELECT語句以提升索引或刪除行。
62:--check-slave-lag:暫停歸檔,直到指定的DSN的slave延遲小於--max-lag。可以多次指定此選項以檢查多個從庫。
63:--check-interval:檢查從庫延遲的間隔時間,默認1s。或則每100行執行一次檢查。
64:--why-quit:除非行耗盡,否則打印退出原因。
注意:下面幾個參數都是互斥的,只能選其一:
"--ignore" and "--replace" are mutually exclusive. "--txn-size" and "--commit-each" are mutually exclusive. "--low-priority-insert" and "--delayed-insert" are mutually exclusive. "--share-lock" and "--for-update" are mutually exclusive. "--analyze" and "--optimize" are mutually exclusive. "--no-ascend" and "--no-delete" are mutually exclusive.
使用場景
注意: 歸檔的表大小寫敏感,表必須至少有一個索引(Cannot find an ascendable index in table )。
①:導出到文件,不刪除源數據(--no-delete,默認刪除):
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc --file=/tmp/%Y-%m-%d-%D.%t --where="1=1" --no-delete --no-safe-auto-increment --progress=1000 --statistics
分析:從general_log里看到的流程是:source服務器讀取一條,file寫入一條,可以通過--txn-size進行指定行數的提交。這里需要注意的是,根據自增id進行歸檔的話,默認最大的id不會進行歸檔,需要添加參數:--no-safe-auto-increment 才能對最大id進行處理。
②:刪除,不導出和遷移:
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc --purge --where="1=1" --no-safe-auto-increment --progress=100 --statistics

分析: 從general_log里看到的流程是:source服務器讀取一條再刪除一條提交,可以加上--txn-size進行多個刪除放到一個事務提交。
③:全表歸檔(遷移),源表不刪除,非批量
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="1=1" --progress=1000 --statistics --no-delete

分析:從general_log里看到的流程是:source服務器讀取一條,dest服務器寫入一條並commit,source再delete並commit(如果刪除源數據)。
④:全表歸檔(遷移),源表不刪除,批量插入
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="1=1" --progress=1000 --limit=1000 --statistics --bulk-insert --txn-size=1000 --no-delete

分析:從general_log里看到的流程是:source服務器讀取一個范圍【FORCE INDEX(`PRIMARY`) WHERE (1=1) AND (`id` < '4999') AND ((`id` > '2733'))】,dest服務器通過【LOAD DATA LOCAL INFILE】進行批量插入。
⑤:全表歸檔(遷移),源表刪除,批量插入,批量刪除
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="1=1" --progress=1000 --limit=1000 --statistics --bulk-insert --bulk-delete --txn-size=1000

分析:從general_log里看到的流程是:source服務器讀取一個范圍【FORCE INDEX(`PRIMARY`) WHERE (1=1) AND (`id` < '4999') AND ((`id` > '2733'))】,dest服務器通過【LOAD DATA LOCAL INFILE】進行批量插入,source再delete【WHERE (((`id` >= '1'))) AND (((`id` <= '2733'))) AND (1=1) LIMIT 1000】並commit。這里需要注意的是,根據自增id進行歸檔的話,默認最大的id不會進行歸檔,需要添加參數:--no-safe-auto-increment 才能對最大id進行處理。
⑥:指定條件歸檔,源表刪除,批量(每1000個插入提交一次),如果源表不刪除,加上--no-delete即可。
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="id<=49999" --progress=1000 --statistics --bulk-insert --bulk-delete --txn-size=1000 --limit=1000
⑦:指定索引的歸檔,不走自增主鍵索引。參數:i
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc,i=idx_age --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="age >=80000 and age<100000" --progress=1000 --statistics --bulk-insert --bulk-delete --txn-size=1000 --limit=1000 --no-delete
⑧:有從庫的歸檔,從庫延遲大於1s就暫停歸檔:--check-slave-lag
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc,i=idx_age --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="age >=100000 and age<150000" --progress=1000 --statistics --bulk-insert --bulk-delete --txn-size=1000 --limit=1000 --no-delete --max-lag=1 --check-slave-lag u=root,p=dba,h=10.24.35.181,P=16500

當從庫延遲小於--max-lag設置的時間之后,繼續歸檔。要是有多個從庫的話,繼續指定--check-slave-lag參數,該參數可以重復指定多個從庫。
⑨:不做任何操作,只打印要執行的查詢語句
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc,i=idx_age --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --where="age >=80000 and age<100000" --progress=1000 --statistics --replace --txn-size=1000 --limit=1000 --no-delete --dry-run
![]()
⑩:常用的命令:歸檔到另一個數據庫,源表刪除,批量刪除和插入,每1000次修改進行提交。跳過錯誤並且指定字符集連接。
pt-archiver --source u=root,p=dba,h=100.47.47.47,P=16500,D=sbtest,t=abc,i=idx_age --dest u=root,p=dba,h=100.47.47.47,P=17500,D=sbtest,t=ABC --no-version-check --charset=UTF8 --where="age >=100000 and age<500000" --ignore --txn-size=1000 --limit=1000 --bulk-delete --bulk-insert --progress=5000 --statistics --why-quit
可以根據自己的實際情況,進行相關參數的調整。另外其他相關參數說明:
--ignore或則--replace:歸檔沖突記錄跳過或則覆蓋,批量插入的時候因為是load data,索引看不到主鍵沖突記錄的報錯。要是非批量插入,則需要添加。 --sleep:指定兩次SELECT語句的sleep時間.默認是沒有sleep的。 --why-quit:打印退出的原因,歸檔數據正常完成的除外。 --charset=UTF8:指定字符集。 --analyze:結束歸檔后,優化表空間。
常用的參數:
| --where 'id<3000' | 設置操作條件 |
| --limit 10000 | 每次取1000行數據給pt-archive處理 |
| --txn-size 1000 | 設置1000行為一個事務提交一次 |
| --progress 5000 | 每處理5000行輸出一次處理信息 |
| --statistics | 結束的時候給出統計信息:開始的時間點,結束的時間點,查詢的行數,歸檔的行數,刪除的行數,以及各個階段消耗的總的時間和比例,便於以此進行優化。只要不加上--quiet,默認情況下pt-archive都會輸出執行過程的 |
| --charset=UTF8 | 指定字符集為UTF8 |
| --no-delete | 表示不刪除原來的數據,注意:如果不指定此參數,所有處理完成后,都會清理原表中的數據 |
| --bulk-delete | 批量刪除source上的舊數據 |
| --bulk-insert | 批量插入數據到dest主機 (看dest的general log發現它是通過在dest主機上LOAD DATA LOCAL INFILE插入數據的) |
| --purge | 刪除source數據庫的相關匹配記錄 |
| --local | 不把optimize或analyze操作寫入到binlog里面(防止造成主從延遲巨大) |
| --analyze=ds | 操作結束后,優化表空間(d表示dest,s表示source) 默認情況下,pt-archiver操作結束后,不會對source、dest表執行analyze或optimize操作,因為這種操作費時間,並且需要你提前預估有足夠的磁盤空間用於拷貝表。一般建議也是pt-archiver操作結束后,在業務低谷手動執行analyze table用以回收表空間 |
注意:批量操作和單條操作提交性能有近10倍的差距。
總結
pt-archiver實現的功能很簡單,工具也很輕量,能非常好的對數據進行低影響的歸檔和刪除,支持大部分場景。需要注意的是,畢竟是操作生產數據,使用之前還得多測試,根據實際情況進行參數的調整優化。
