1. 程式人生 > >percona-toolkit 之 【pt-archiver】

percona-toolkit 之 【pt-archiver】

背景:

        工作上需要刪除或則歸檔一張大表,這時候用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::指定要歸檔表的資訊,相容

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

2::指定要歸檔到的表,相容DSN選項。

此項指定一個表,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::連線MySQL時提示輸入密碼。

7:--buffer:緩衝區輸出到--file並在提交時重新整理,每次事務提交禁止刷寫到磁碟,有作業系統決定刷寫。該引數可以提高刷寫到檔案的效能,但崩潰可能會有資料丟失。

8:--commit-each:控制事務大小,每次提取、歸檔就提交。禁用--txn-size。

9:--config:以逗號分隔的配置檔案列表; 如果指定,則必須是命令列上的第一個選項。

10::D,連線時使用的預設資料庫。

11:--delayed-insert:在insert後面新增delayed,延遲寫入。

12::列印查詢並退出而不做任何事情。

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儲存檔案。

17::連線的MySQL地址。

18::insert語句加入ignore。

19:--local:新增NO_WRITE_TO_BINLOG引數,OPTIMIZE 和 ANALYZE不寫binlog。

21:--low-priority-insert:每隔insert和replace語句加入LOW_PRIORITY。

由--check-slave-lag給出的從延遲。獲取行時檢視從庫,如果slave的延遲大於選項的值,或者slave沒有執行(因此它的滯後為NULL),則pt-table-checksum會休眠--check-interval seconds,然後再次檢視滯後。 它會一直重複,直到slave小於該引數,然後繼續獲取並歸檔該行。

23::不要刪除存檔的行,預設會刪除。不允許--no-ascend,因為啟用它們都會導致無限迴圈。

24:--optimize:在--source或--dest上執行之後OPTIMIZE TABLE。

25:--output-format:與--file一起使用以指定輸出格式,格式相當於FIELDS TERMINATED BY','OPTIONALLY ENCLOSED BY'''。

26::-p,連線MySQL時使用的密碼。 如果密碼包含逗號,則必須使用反斜槓進行轉義。

27:--pid:建立給定的PID檔案。 如果PID檔案已存在並且其包含的PID與當前PID不同,則該工具將不會啟動。 但是,如果PID檔案存在且其包含的PID不再執行,則該工具將使用當前PID覆蓋PID檔案。 退出工具時會自動刪除PID檔案。

28::-P,連線MySQL時的埠。

僅限主鍵列。用於指定具有主鍵列的--columns的快捷方式,當DELETE語句只需要主鍵列時,它可以避免獲取整行。

30::每多少行列印進度資訊:列印當前時間,已用時間以及每X行存檔的行數。

31::清除而不是歸檔; 允許省略--file和--dest。如果只想清除行,請考慮使用--primary-key-only指定表的主鍵列。 這樣可以防止無緣無故地從伺服器獲取所有列。

32:--quick-delete:delete語句裡新增quick。

33:--quite:-q,不列印任何輸出,包括--statistics的輸出,對--why-quit的輸出無效。

34::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。

44::指定SELECT語句之間的休眠時間。 預設不sleep。 未提交事務,並且在休眠之前不會重新整理--file檔案。如果指定了--commit-each,則在休眠之前發生提交和重新整理。

45:--sleep-coef:pt-archiver將在最後一次SELECT乘以指定係數的查詢時間內休眠。在每個SELECT之間休眠不同的時間,具體取決於SELECT所花費的時間。

46:--socket:-S,用於連線的套接字檔案。

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::每個事務的行數,預設1。指定每個事務的大小(行數)。0完全禁用事務。在pt-archiver處理這麼多行之後,如果指定該引數,它會提交--source和--dest,並重新整理--file給出的檔案。

此引數對效能至關重要。如果要從實時伺服器(例如正在執行大量OLTP工作)進行存檔,則需要在事務大小和提交開銷之間選擇良好的平衡。較大的事務會產生更多的鎖爭用和死鎖,但較小的事務會導致更頻繁的提交開銷,如果沒有從事務儲存引擎進行歸檔,則可能需要禁用事務。

50::-u,連線MySQL時的使用者。

53::指定WHERE子句以限制存檔的行。 子句裡不要包含單詞WHERE,不需要WHERE子句,請使用--where 1=1。如:

--where 'ts < current_date - interval 90 day'

54::限制檢索要歸檔的行的SELECT語句返回的行數,預設是1。這可能會導致與其他查詢的更多爭用,具體取決於儲存引擎,事務隔離級別和--for-update等選項。

55::使用單個DELETE語句批量刪除每個行塊。該語句刪除塊的第一行和最後一行之間的每一行,隱含--commit-each。

56:--[no]bulk-delete-limit:新增--limit到--bulk-delete語句,預設yes。

57:--bulk-insert:使用LOAD DATA LOCAL INFILE插入每個行塊。 比使用INSERT語句一次插入行快得多。 通過為每個行塊建立一個臨時檔案,並將行寫入此檔案而不是插入它來實現的。此選項會強制使用批量刪除。

58::-A,設定預設字符集。

59::不檢查字符集, 禁用此檢查可能會導致文字被錯誤地從一個字符集轉換為另一個字符集。進行字符集轉換時,禁用此檢查可能有用。

60:--[no]check-columns:檢查--source和--dest具有相同的列,預設yes。它不檢查列順序,資料型別等。它只檢查源中的所有列是否存在於目標中。存在差異則退出。不檢查則用引數–no-check-columns。

61::指定歸檔的列,以逗號分隔的列的列表以獲取寫入檔案並插入目標表。 如果指定,將忽略其他列,除非它需要將它們新增到SELECT語句以提升索引或刪除行。

62::暫停歸檔,直到指定的DSN的slave延遲小於--max-lag。可以多次指定此選項以檢查多個從庫。可以通過--recursion-method來指定想要監控的物件。

63::檢查從庫延遲的間隔時間,預設1s。或則每100行執行一次檢查。

64::除非行耗盡,否則列印退出原因。

注意:下面幾個引數都是互斥的,只能選其一:

"--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實現的功能很簡單,工具也很輕量,能非常好的對資料進行低影響的歸檔和刪除,支援大部分場景。需要注意的是,畢竟是操作生產資料,使用之前還得多測試,根據實際情況進行引數的調整優化。