MySQL備份遷移之mydumper

immaxfang發表於2022-04-25

簡介

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的學習札記

相關文章