mydumper備份mysql資料庫
mydumper介紹
MySQL自身的mysqldump工具支援單執行緒工作,依次一個個匯出多個表,沒有一個並行的機制,這就使得它無法迅速的備份資料。
mydumper作為一個實用工具,能夠良好支援多執行緒工作,可以並行的多執行緒的從表中讀入資料並同時寫到不同的檔案裡,這使得它在處理速度方面快於傳統的mysqldump。其特徵之一是在處理過程中需要對列表加以鎖定,因此如果我們需要在工作時段執行備份工作,那麼會引起DML阻塞。但一般現在的MySQL都有主從,備份也大部分在從上進行,所以鎖的問題可以不用考慮。這樣,mydumper能更好的完成備份任務。
mydumper特性
多執行緒備份 因為是多執行緒邏輯備份,備份後會生成多個備份檔案 備份時對MyISAM表施加FTWRL(FLUSH TABLES WITH READ LOCK),會阻塞DML語句 保證備份資料的一致性 支援檔案壓縮 支援匯出binlog 支援多執行緒恢復 支援以守護程序模式工作,定時快照和連續二進位制日誌 支援將備份檔案切塊
mydumper的安裝
mydumper使用c語言編寫,使用glibc庫
mydumper安裝所依賴的軟體包 yum install glibc zlib pcre pcre-devel gcc gcc-c++ cmake make -y
安裝依賴軟體包,將mysql客戶端庫檔案路徑新增至/etc/ld.so.conf, 如/usr/local/mysql/lib
wget https://github.com/maxbube/mydumper/releases/download/v0.9.5/mydumper-0.9.5-2.el7.x86_64.rpm 安裝完成後生成兩個二進位制檔案mydumper和myloader位於/usr/local/bin目錄下
主要步驟概括
(1)主執行緒 FLUSH TABLES WITH READ LOCK, 施加全域性只讀鎖,以阻止DML語句寫入,保證資料的一致性 (2)讀取當前時間點的二進位制日誌檔名和日誌寫入的位置並記錄在metadata檔案中,以供即使點恢復使用 (3)N個(執行緒數可以指定,預設是4)dump執行緒 START TRANSACTION WITH CONSISTENT SNAPSHOT; 開啟讀一致的事物 (4)dump non-InnoDB tables, 首先匯出非事物引擎的表 (5)主執行緒 UNLOCK TABLES 非事物引擎備份完後,釋放全域性只讀鎖 (6)dump InnoDB tables, 基於事物匯出InnoDB表 (7)事物結束
備份所生成的檔案
所有的備份檔案在一個目錄中,目錄可以自己指定 目錄中包含一個metadata檔案 記錄了備份資料庫在備份時間點的二進位制日誌檔名,日誌的寫入位置,
如果是在從庫進行備份,還會記錄備份時同步至主庫的二進位制日誌檔案及寫入位置
每個表有兩個備份檔案: database.table-schema.sql 表結構檔案
database.table.sql 表資料檔案
如果對錶檔案分片,將生成多個備份資料檔案,可以指定行數或指定大小分片
mydumper和myloader的使用
mydumper引數
-B, --database 要備份的資料庫,不指定則備份所有庫 -T, --tables-list 需要備份的表,名字用逗號隔開 -o, --outputdir 備份檔案輸出的目錄 -s, --statement-size 生成的insert語句的位元組數,預設1000000 -r, --rows 將表按行分塊時,指定的塊行數,指定這個選項會關閉 --chunk-filesize -F, --chunk-filesize 將表按大小分塊時,指定的塊大小,單位是 MB -c, --compress 壓縮輸出檔案 -e, --build-empty-files 如果表資料是空,還是產生一個空檔案(預設無資料則只有表結構檔案) -x, --regex 是同正則表示式匹配 'db.table' -i, --ignore-engines 忽略的儲存引擎,用都厚分割 -m, --no-schemas 不備份表結構 -d, --no-data 不匯出表資料 -G, --triggers 匯出觸發器 -E, --events 匯出事件 -R, --routines 匯出儲存過程 -k, --no-locks 不使用臨時共享只讀鎖,使用這個選項會造成資料不一致 -l, --long-query-guard 設定阻塞備份的長查詢超時時間,單位是秒,預設是60秒(超時後預設mydumper將會退出) -K, --kill-long-queries kill掉長時間執行的查詢,備份報錯:Lock wait timeout exceeded; try restarting transaction
-D, --daemon 啟用守護程序模式,守護程序模式以某個間隔不間斷對資料庫進行備份 -I, --snapshot-interval dump快照間隔時間,預設60s,需要在daemon模式下 -L, --logfile 使用的日誌檔名(mydumper所產生的日誌), 預設使用標準輸出 -h, --host 連線的主機名 -u, --user 備份所使用的使用者 -p, --password 密碼 -P, --port 埠 -S, --socket 使用socket通訊時的socket檔案 -t, --threads 開啟的備份執行緒數,預設是4 -C, --compress-protocol 壓縮與mysql通訊的資料 -V, --version 顯示版本號 -v, --verbose 輸出資訊模式, 0 = silent, 1 = errors, 2 = warnings, 3 = info, 預設為 2 --lock-all-tables 鎖全表,代替FLUSH TABLE WITH READ LOCK --tz-utc 備份的時候允許備份Timestamp,這樣會導致不同時區的備份還原會出問題,預設禁用 --skip-tz-utc 同上 --use-savepoints 使用savepoints來減少採集metadata所造成的鎖時間,需要 SUPER 許可權 --success-on-1146 Not increment error count and Warning instead of Critical in case of table doesn't exist --less-locking 減少對InnoDB表的鎖施加時間(這種模式的機制下文詳解)
myloader使用引數
-d, --directory 備份檔案的資料夾 -q, --queries-per-transaction 每次事物執行的查詢數量,預設是1000 -o, --overwrite-tables 如果要恢復的表存在,則先drop掉該表,使用該引數,需要備份時候要備份表結構 -B, --database 需要還原的資料庫 -e, --enable-binlog 啟用還原資料的二進位制日誌 -h, --host 主機 -u, --user 還原的使用者 -p, --password 密碼 -P, --port 埠 -S, --socket socket檔案 -t, --threads 還原所使用的執行緒數,預設是4 -C, --compress-protocol 壓縮協議 -V, --version 顯示版本 -v, --verbose 輸出模式, 0 = silent, 1 = errors, 2 = warnings, 3 = info, 預設為2
關閉寫入日誌到二進位制中。主從不會複製。 myloader -u root -p 'mysql' -h localhost -B online20180801 -o -t 4 -v 3 -d /db/20180827/ -S /db/mysql_3306/mysql.sock
開啟 -e: myloader -u root -p 'mysql' -h localhost -B online20180801 -o -t 4 -v 3 -e -d /db/20180827/ -S /db/mysql_3306/mysql.sock
(1)備份指定庫,並壓縮備份檔案 mydumper -u root -p ### -h localhost -B online -c -o /backup/01
(2)全備,並備份二進位制日誌檔案。 mydumper -u root -p ### -h localhost -o /backup/02
(3)備份表,不備份表結構。 mydumper -u root -p ### -h localhost -B online -T tb_player accitem_list -m -o /backup/03
(4)指定備份資料庫:備份mysql和test庫: mydumper -u backup -p 123456 -h 192.168.180.13 -P 3306 -t 3 -c -l 3600 -s 10000000 -e --regex '^(mysql\.|test\.)' -o bbb/
(5)指定不備份的資料庫:不備份abc、mysql、test,備份其他資料庫 mydumper -u backup -p 123456 -h 192.168.180.13 -P 3306 -t 3 -c -l 3600 -s 10000000 -e --regex '^(?!(abc\.|mysql\.|test\.))' -o bbb/
(6)不備份以test開頭的庫:--regex '^(?!(test))'
mydumper -u backup -p 123456 -h 192.168.180.13 -P 3306 -t 3 -c -l 120 -B online -G -E -R -r 500000 -K -C\ --build-empty-files --socket=/tmp/mysql.sock -o tmp/
或者: mydumper \ --database=online \ --host=localhost \ --port=3306 \ --user=root \ --password='mysql' \ --outputdir=/app/tmp \ --rows=500000 \ --compress \ --build-empty-files \ --threads=3 \ --verbose=3 \ --compress-protocol \ --kill-long-queries \ --triggers \ --events \ --routines \ --less-locking \ --long-query-guard=120 \ --socket=/tmp/mysql.sock
導資料,全備註意,不要匯出sys,
還原 myloader -u root -p ### -h localhost -B sltonline -d sltonline/
全備的,還原不要指定--database。他自動會建立 myloader \ --database=sltonline \ --host=localhost \ --port=3306 \ --user=root \ --password='' \ --directory=tmp/20180613/ \ --queries-per-transaction=50000 \ --threads=6 \ --compress-protocol \ --verbose=3 \ --overwrite-tables \ --socket=/db/mysql_3306/mysql.sock
mydumper的less locking模式
mydumper使用--less-locking可以減少鎖等待時間,此時mydumper的執行機制大致為
主執行緒 FLUSH TABLES WITH READ LOCK (全域性鎖) Dump執行緒 START TRANSACTION WITH CONSISTENT SNAPSHOT; LL Dump執行緒 LOCK TABLES non-InnoDB (執行緒內部鎖) 主執行緒UNLOCK TABLES LL Dump執行緒 dump non-InnoDB tables LL DUmp執行緒 UNLOCK non-InnoDB Dump執行緒 dump InnoDB tables
mydumper把資料和表結構分開備份,並且把二進位制日誌備份出來單獨放到一個檔案中。
*_post.sql.gz 備份的是儲存過程。檢視被當成表進行了備份。
------------------------------------------------ 刪除部分備份檔案,不執行匯入:
for ((i=247;i<=250;i++));do var=$(printf "%05d" "$i");echo online.msg01_base.$var.sql.gz;done
解壓mydumper的壓縮檔案。 gunzip -c db1-schema-create.sql.gz >test.sql
=============================================================
增量備份,根據測試和上面的原理來看,binlog位置表示的是:FLUSH TABLES WITH READ LOCK 之前的資料, 之後插入的資料,不會被備份進去。因此如果要增量備份,那就從該位置開始恢復即可。
因此增量備份,直接cp binlog檔案即可。為了保證每一個binlog檔案的完整型(也就是說不會導致備份之後,該檔案繼續寫入,下次增量的時候又將該檔案備份一次) 每次進行全備和增量備份之前,flush logs一下。
=============================================錯誤收集-===============
匯入的時間出現這個報錯:
** (myloader:766): CRITICAL **: the specified directory is not a mydumper backup
沒有找到備份集,可能路徑錯誤。
** (myloader:10552): CRITICAL **: Error switching to database online20180601,online20180701,sltpay whilst restoring table help_category ** Message: Thread 6 shutting down
原因很多,比如磁碟滿了,記憶體佔用太多被linux kill掉等等。