簡介 mydumper 是一款開源的 MySQL 邏輯備份工具,主要由 C 語言編寫。與 MySQL 自帶的 mysqldump 類似,但是 mydumper 更快更高效。 mydumper 的一些優點特性: 輕量級C語言開發 支持多線程備份數據,備份後按表生成多個備份文件 支持事務性和非事務性表一 ...
簡介
mydumper 是一款開源的 MySQL 邏輯備份工具,主要由 C 語言編寫。與 MySQL 自帶的 mysqldump 類似,但是 mydumper 更快更高效。
mydumper 的一些優點特性:
- 輕量級C語言開發
- 支持多線程備份數據,備份後按表生成多個備份文件
- 支持事務性和非事務性表一致性備份
- 支持將導出的文件壓縮,節約空間
- 支持多線程恢復
- 支持已守護進程模式工作,定時快照和連續二進位日誌
- 支持按指定大小將備份文件切割
- 數據與建表語句分離
下載安裝
安裝方式非常多,以下介紹幾種常見的方式。
- Ubuntu 中自帶了 myloader
sudo apt-get install mydumper
- 使用 deb 包安裝,以 Ubuntu 為例
apt-get install libatomic1
wget https://github.com/mydumper/mydumper/releases/download/v0.11.5/mydumper_0.11.5-1.$(lsb_release -cs)_amd64.deb dpkg -i mydumper_0.11.5-1.$(lsb_release -cs)_amd64.deb
- 編譯安裝
- docker 安裝
根據實際平臺情況,可選擇不同的安裝方式,官方也提供了一些常見的安裝文檔,https://github.com/mydumper/mydumper
參數說明
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 備份存儲過程和函數
-W, --no-views 不備份視圖
--where 只導出符合條件的數據
-k, --no-locks 不使用臨時共用只讀鎖,使用這個選項會造成數據不一致
--less-locking 減少對InnoDB表的鎖施加時間(這種模式的機制下文詳解)
-l, --long-query-guard 設定阻塞備份的長查詢超時時間,單位是秒,預設是60秒(超時後預設mydumper將會退出)
--kill-long-queries 殺掉長查詢 (不退出)
-b, --binlogs 導出binlog
-D, --daemon 啟用守護進程模式,守護進程模式以某個間隔不間斷對資料庫進行備份
-I, --snapshot-interval dump快照間隔時間,預設60s,需要在daemon模式下
-L, --logfile 使用的日誌文件名(mydumper所產生的日誌), 預設使用標準輸出
--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
-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
myloader 參數說明
-d, --directory 備份文件的文件夾
-q, --queries-per-transaction 每次事物執行的查詢數量,預設是1000
-o, --overwrite-tables 如果要恢復的表存在,則先drop掉該表,使用該參數,需要備份時候要備份表結構
-B, --database 還原到的資料庫(目標庫)
-s, --source-db 被還原的資料庫(源資料庫),-s db1 -B db2,表示源庫中的db1資料庫,導入到db2資料庫中。
-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
常用案例
mydumper 導出示例
# 個人實際中最常用的備份語句
mydumper -B test -o /home/mydumper/data/test -e -G -R -E -D -u root -p 123456 -h 192.168.0.191 -P 3306 -v 3 --long-query-guard 288000 --skip-tz-utc --no-locks --logfile /home/mydumper/log/test
# 備份全部資料庫
mydumper -u root -p 123456 -o /home/mydumper/data/all/
# 備份全部資料庫,排除系統庫,
mydumper -u root -p 123456 --regex '^(?!(mysql|sys|performance_schema|information_schema))' -o /home/mydumper/data/all/
# 備份全部資料庫,包含觸發器、事件、存儲過程及函數
mydumper -u root -p 123456 -G -R -E -o /home/mydumper/data/all/
# 備份指定庫
mydumper -u root -p 123456 -G -R -E -B db1 -o /home/mydumper/data/db1
# 備份指定表
mydumper -u root -p 123456 -B db1 -T tb1,tb2 -o /home/mydumper/data/db1
# 只備份表結構
mydumper -u root -p 123456 -B db1 -d -o /home/mydumper/data/db1
# 只備份表數據
mydumper -u root -p 123456 -B db1 -m -o /home/mydumper/data/db1
myloader 導入案例
# 個人實際中最常用的導入語句
myloader -h 192.168.0.192 -P 33306 -u root -p 123456 -t 1 -v 3 -d /home/mydumper/data/test/0/ -B test
# 從備份中恢復指定庫
myloader -u root -p 123456 -s db1 -o -d /home/mydumper/data/all/0/
# 導入時開啟 binlog
myloader -u root -p 123456 -e -o -d /home/mydumper/data/db1/0/
# 將源庫的 db1 導入到備庫的 db1_bak 庫中
myloader -u root -p 123456 -B db1_bak -s db1 -o -d /home/mydumper/data/db1/0/
# 導入特定的某幾張表
## 先將 metadata 文件和需要單獨導入的表的結構文件和數據文件導入到單獨的文件夾中。此處預設庫已建好,否則還需要複製建庫相關語句。
cp /home/mydumper/data/db1/0/metadata /backup/db1/0/
cp /home/mydumper/data/db1/0/d1.t1-schema.sql /backup/db1/0/
cp /home/mydumper/data/db1/0/d1.t1.sql /backup/db1/0/
## 從新文件夾中導入數據
myloader -u root -p 123456 -B db1 -d /backup/db1/0/
## 以上就可以單獨導入 db1.t1 表
關於 -e 參數,需要稍微註意下。預設情況下,myloader 是不開啟 binlog 的,這樣可以提高導入速度。如果導入實例有從庫,且需要導入的結果同步到從庫上,則需要使用 -e 打開 binlog 記錄。
導出之後的目錄如下,以資料庫 d1 ,其中有表 t1 為例:
-d1
-0
metadata 記錄備份時間點的Binlog信息,日誌文件名和寫入位置
d1-schema-create.sql 建庫語句
d1-schema-post.sql 存儲過程,函數,事件創建語句
d1.t1-schema.sql 表結構文件
d1.t1.sql 表數據文件,若使用了分塊參數,大表的數據文件會出現多個,以數字分開。
-1
以上為比較常見的導出後的目錄結構,根據實際情況不同,可能還有會含有觸發器的文件,含有視圖的文件等。
常見問題與實踐經驗
- Error switching to database whilst restoring table
使用 myloader 導入時會出現這類報錯,可以嘗試的解決方法如下:調大 wait_timeout 參數;調大 max_packet_size 參數;使用一個線程導入, -t 1。
- (myloader:35671): CRITICAL **: Error restoring test.email_logger from file test.email_logger.sql: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
MySQL 的一個 Bug,可以嘗試手動修改對應的備份文件,將
/!40101 SET NAMES binary/;
修改為:
/!40101 SET NAMES utf8mb4/;
- (myloader:34726): CRITICAL **: Error restoring test.(null) from file test-schema-post.sql: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
在導入 AWS RDS 時部分存儲過程創建失敗,有比較嚴格的許可權限制,需要導入用戶有 SUPER 許可權,但是 AWS RDS 用戶無法授予 SUPER 許可權。針對這部分存儲過程,可以考慮手動在備份庫上創建。
- 大表導出優化
使用 -r
或-F
參數,對導出的數據文件進行分片。
- 備份機器配置儘可能高
備份前先預估大小,避免機器磁碟不足。儘可能選用配置較高的機器,加快備份速度。
- 非必要數據不備份
備份前對於不用備份的數據可以提前進行一次刪除,也可在導出數據時添加正則參數等過濾部分表
- 備份儘量不跨網路
備份數據時儘量在內網中進行,若需要將數據遷移到外網,可以備份完之後,將備份文件拷貝到外網伺服器上,儘量減少導出時網路不穩定的干擾。導入時同理。
- 加快導入速度的一些方法
選擇合適的線程數,根據實際情況和機器配置,選擇合適的線程參數,並非線程數越多越快。
導入時關閉 MySQL 的 binlog 寫入,待導入完成後再開啟。
在內網或較穩定的環境中進行導入。
原理與架構
mydumper 工作流程
主要步驟概括
- 主線程 FLUSH TABLES WITH READ LOCK,施加全局只讀鎖,阻止DML語句寫入,保證數據的一致性。
- 讀取當前時間點的二進位日誌文件名和日誌寫入的位置並記錄在metadata文件中。
- N個dump線程 START TRANSACTION WITH CONSISTENT SNAPSHOT,開啟讀一致的事務。
- dump non-InnoDB tables, 首先導出非事物引擎的表。
- 主線程 UNLOCK TABLES 非事物引擎備份完後,釋放全局只讀鎖。
- dump InnoDB tables,基於事物導出InnoDB表。
- 事務結束。
myloader 工作原理
更多技術文章,請關註我的個人博客 www.immaxfang.com 和小公眾號 Max的學習札記
。