mydumper使用及原理淺析

神諭丶發表於2020-10-07

安裝

yum 
install -y glib2-devel mysql-devel zlib-devel pcre-devel openssl-devel cmake gcc gcc-c++  

git  clone 
cd mydumper  
cmake .  
make && make  install  

備份

用法十分簡單,如需要做 全例項備份


mydumper -u 
$user -p 
$password -h 
$host -G -E -R -c -o /data/backup --less-locking   

使用的時候,需要隔開選項和對應的值,比如-uroot要寫成-u root,否則會報錯


option parsing failed: 
Error parsing 
option -r, 
try --help  

-u -p -S/-h 這個肯定要指定,含義和 mysqldumpmysqlmysqladmin等工具一致


-B 指定資料庫 (如果沒有-B,預設就是全庫表)  

-G 備份trigger  
-E 備份event  
-R 備份routine  
-c 壓縮(gzip)  
-x 正則,比如備份多個指定的庫:-x 'test|mysql',比如指定某些庫不參與備份:-x '^(?!(sys|mysql))'   
-T 指定表,如-T test.tb1  
-t 執行緒數,預設4  
-l 設定長查詢的閾值  
-K 加上這個引數,會考慮-l指定的時間,如果超過這個閾值,會將阻塞備份程式的會話幹掉  
--less-locking 減少InnoDB表的鎖時間  
--trx-consistency-only 代表本次備份只對事務表做一致性保證  
--skip-tz-utc 不加的話,會在dump的時候加上SET TIME_ZONE='+00:00'  


如果想看dump時詳細的資訊輸出,可以指定 --verbose=3,日誌級別為 info,預設不指定,為 warning(2)  

備份輸出格式及內容

metadata記錄的內容,基本上等同於 mysqldump--master-data--set-gtid-purged  

cat 
metadata   

Started  dump  at: 2019 -03-25 16 :23:48  
SHOW  MASTER  STATUS:  
         Logmysql57-bin .000012  
         Pos: 749818446  
         GTID :ba5fdbe3-4949-11e8-8d33-525400652955:1-2  

Finished  dump  at: 2019 -03-25 16 :24:04  

*-schema.sql.gz為表結構


# zcat mysql.gtid_executed-schema.sql.gz  

/*!40101 SET NAMES binary*/;  
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;  
/*!40103 SET TIME_ZONE='+00:00' */;  
CREATE  TABLE  `gtid_executed` (  
   `source_uuid`  char( 36NOT  NULL  COMMENT  'uuid of the source where the transaction was originally executed.',  
   `interval_start`  bigint( 20NOT  NULL  COMMENT  'First number of interval.',  
   `interval_end`  bigint( 20NOT  NULL  COMMENT  'Last number of interval.',  
  PRIMARY  KEY ( `source_uuid`, `interval_start`)  
ENGINE= InnoDB  DEFAULT  CHARSET=latin1 STATS_PERSISTENT= 0;  

.sql.gz為表資料


# zcat mysql.gtid_executed.sql.gz | head -5  

/*!40101 SET NAMES binary*/;  
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;  
/*!40103 SET TIME_ZONE='+00:00' */;  
INSERT  INTO  `gtid_executed`  VALUES  
( "ba5fdbe3-4949-11e8-8d33-525400652955", 1, 2);  

在加了-B或者預設全庫備份的場景下,還會有一個建立schema的檔案:


# zcat mysql-schema-create.sql.gz  

CREATE  DATABASE  `mysql`  /*!40100 DEFAULT CHARACTER SET latin1 */;  

恢復

myloader -u 
$user -p 
$password -h 
$host -d /data/backup/  

常用可選引數:


-e,加了-e之後,匯入的時候會記錄binlog  

-t 同樣是執行緒數,這個預設也是4  

備份和恢復速度

這個沒測了。  
同事測了,反正就是快。(當然沒 xtrabackup快)

原理

老規矩,策略是用 general_log分析一下:


SET 
GLOBAL general_log=
ON;  

SET  GLOBAL log_output= 'TABLE';  
TRUNCATE  TABLE mysql.general_log;  

再在備份的時候開啟 --verbose=3,為了簡明,我去掉了-G -E -R,意思是不備份 trigger、event、routine,且dump執行緒指定為2個。

測試庫為test,表為a_myisam(MyISAM)、b_myisam(MyISAM)、t_1(InnoDB)、t_db_backup(InnoDB)

原理分析,主要是圍繞加與不加 --trx-consistency-only--less-locking,並且為了瞭解如何並行dump,和對存在非事務引擎時,如何拿到邏輯一致性的備份。

先分析過程, 如果不想細看可以直接拉到底看結論

① 不加--less-locking:

測試命令:

mydumper -u 
$user -p 
$password -h 
$host -c -o /data/backup/ --verbose=3 -B 
test -t 2   

根據 mysql.general_logthread_idargument一起分析一下:


SELECT thread_id, command_type, 
left(argument,
80

FROM mysql.general_log;


跑上述sql,可以拉到如下結果:

 可以看到,主執行緒374,先把 wait_timeoutnet_write_timeout給調大,然後跑個其他備份工具都愛加的全域性讀鎖: FTWRL,成功後,再來個 START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */,保證是一致性讀,接下來看 master status,記錄下 log_filelog_pos,如果為slave,也拉了slave的資訊(此處未測slave的環境)

 然後此處我指定的 -t 2,意思是分兩個dump執行緒來備份,此處可以看到375和376連上來了:同樣先調大 timeout兩個引數,並先將隔離級別改為RR,無論關引擎,因現在還沒開始判斷表引擎。

 主執行緒374開始判斷表引擎, SHOW TABLE STATUS,這樣可以告訴dump執行緒,哪些是非事務引擎,因為需要在 FTWRL的情況下先備份

 兩個dump執行緒開始備份非事務引擎,此處是 a_myisamb_myisam,直至備份結束。

 主執行緒374開始 unlock tables,之後,業務可寫。同時,接下來的事情也和主執行緒沒關係了,quit退出。

 兩個dump執行緒繼續備份剩餘的事務表

這樣,多個執行緒並行dump時,所讀到的內容在時間上是一致性的。

雖然這樣備份,備份是一致性的,但如果非事務引擎的表很多且很大,這樣備份,會不會有點不妥?要等非事務引擎備份完,才可 UNLOCK TABLES然後dump事務表。
然後, mydumper就多了這樣一個引數 --less-locking(mydumper 0.6.x後支援)

② 加上--less-locking:

測試命令:

mydumper -u 
$user -p 
$password -h 
$host -c -o /data/backup/ --verbose=3 -B 
test -t 2 --less-locking


同樣,看一下general log輸出

可以很明顯發現,雖然指定了dump併發數為2,但是總共有5個執行緒。
翻了下percona的部落格,發現 --less-locking的選項的加入,為每個 dump thread,多分配了一個 LL dump thread(即 less-locking dump thread)。

那麼整個過程就變成了:  
 主執行緒377依然先調兩個 timeout引數,然後申請全域性讀鎖 FTWRL,並開啟一個事務,記錄file和pos點,這一步與不加 --less-locking一致

 less-lokcing dump執行緒378、379連上來,設定 timeout,並等待主執行緒push非事務表到佇列中。(這裡就不需要開事務了,因為LL dump執行緒是負責非事務引擎的)

 dump執行緒380、381連上來,設定 timeout,改隔離級別為RR,開啟事務,並等待主執行緒分配事務表(380和381則只負責事務表)

 主執行緒377開始透過 SHOW TABLE STATUS判斷非事務表和事務表

 less-locking dump執行緒378、379拿到了兩張非事務表的任務,開始 單獨地拿兩張非事務表的鎖,每個執行緒一個拿到後,就可以開始備份非事務引擎了。

 因為非事務引擎表被單獨的less-locking dump執行緒拿到了鎖,對於主執行緒377,可以執行 UNLOCK TABLES了,這時,全域性讀鎖 FTWRL被釋放,整個過程就減少了事務表的鎖時間。

 開始備份剩下沒備份的事務表,直至退出

引入less-locking dump執行緒,不僅依然可以拿到非事務引擎和事務引擎混合的一致性備份,也可以減少對事務引擎鎖的時間。
實際上,②和③順序也是可以調換的(應該是並行的),在mydumper跑備份的時候,輸出裡stdout可以體現,節選如下:

…………

**  Message: Thread  3 connected using MySQL connection ID  378
**  Message: Thread  4 connected using MySQL connection ID  379
**  Message: Thread  1 connected using MySQL connection ID  380
**  Message: Thread  2 connected using MySQL connection ID  381
**  Message: Thread  4 dumping data  for `test`.`b_myisam`
**  Message: Thread  3 dumping data  for `test`.`a_myisam`
…………

③ 加--trx-consistency-only,(此處加不加--less-locking,過程和結果是一樣的)

首先看一下這個引數是什麼個意思:

WARNING **: 
Using trx_consistency_only, binlog coordinates will 
not be accurate 
if you are 

writing  to non transactional tables.

那麼實際上和隔壁的 --single-transaction的效果是一樣的——只管事務表,如果在備份過程中對非事務表有寫操作,那binlog位置點不準。

所以,加不加 --less-locking就無所謂了,因為不對非事務引擎負責,過程均一致,大致如下:

這種情況,如果有非事務表,且存在寫入的情況下,備份就不是一致性的了,整個過程十分簡單:

 主執行緒調兩個 timeout引數,然後依然申請全域性讀鎖 FTWRL,再開啟事務,記錄file和pos點

 dump執行緒389、390開事務

 主執行緒釋放全域性讀鎖並退出,此處還特意說明了 trx-only

 dump執行緒開始備份

總結

  • 不加--less-locking

① 主執行緒:FTWRL;

② dump執行緒: START  TRANSACTION  WITH  CONSISTENT  SNAPSHOT; dump non-InnoDB tables;
③ 主執行緒: UNLOCK  TABLES;
④ dump執行緒:dump InnoDB tables;
  • 加--less-locking:

① 主執行緒:FTWRL;

② dump執行緒: START  TRANSACTION  WITH  CONSISTENT  SNAPSHOT;
③ LL dump執行緒: LOCK  TABLES non- InnoDB;
④ 主執行緒: UNLOCK  TABLES
⑤ LL dump執行緒:dump non- InnoDB  tablesUNLOCK non- INNODB;
⑥ dump執行緒:dump InnoDB tables;

平時用的話,似乎也可以不用判斷是否有非事務引擎(當然最好不要用!),直接less-locking應該就能夠滿足需求了,日誌級別我習慣設定為info。

對TokuDB似乎是可以支援的,但以前粗淺測過,且沒細看。好像仍是拿不到一致性點的情況,這一點後續待校驗。

mydumper -u 
$user -p 
$password -h 
$host -G -E -R -c --less-locking -o /data/backup/ \ 

--verbose=3 -B  test -t 8 -L /tmp/mydumper_`date +%Y%m%d%H%M%S`. log

其他

mydumper版本:0.9.5
MySQL版本:5.7.21

參考文件

mydumper-less-locking:

https://www.percona.com/blog/2014/06/13/mydumper-less-locking/



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29773961/viewspace-2725573/,如需轉載,請註明出處,否則將追究法律責任。

相關文章