mysqldump 是 MySQL 官方邏輯備份工具,參數繁多且默認行為有坑。本文基於實戰總結「最佳姿勢」:最小化鎖定、獲取一致性備份、保留 Binlog 位點、分離系統庫備份、增量策略、Slave 搭建優化、還原實戰演練。
| 默認行為 | 問題 | 優化參數 |
|---|---|---|
--lock-tables (默認開啟) | 全庫鎖表,阻塞寫入,備份窗口長業務受影響 | --single-transaction (InnoDB) / --lock-all-tables (需一致性時) |
--add-drop-table | 生成 DROP TABLE IF EXISTS,誤執行導致數據丟失 | --skip-add-drop-table 或 --add-drop-table=0 |
無 --master-data | 備份無 Binlog 位點,無法用於搭建 Slave / PITR | --master-data=2 (註釋形式輸出 CHANGE MASTER) |
無 --routines | 不備份存儲過程/函數 | --routines |
--flush-logs + --delete-master-logs | 備份後刪除舊 Binlog,極度危險 | 去掉 --delete-master-logs,備份後手動歸檔 Binlog |
# 1. 業務庫備份 (InnoDB 為主,單事務一致性,記錄 Binlog 位點)
mysqldump -u$USER -p$PASS \
--single-transaction \
--master-data=2 \
--routines \
--flush-logs \
--databases db1 db2 db3 \
> /backup/full_$(date +%F_%H-%M-%S).sql
# 2. 系統庫 mysql 獨立備份 (MyISAM 表需刷新權限)
mysqldump -u$USER -p$PASS \
--flush-privileges \
--databases mysql \
> /backup/mysql_$(date +%F_%H-%M-%S).sql
# 3. 合併備份 (若堅持單文件)
mysqldump -u$USER -p$PASS \
--single-transaction \
--master-data=2 \
--routines \
--flush-logs \
--flush-privileges \
--all-databases \
> /backup/alldb_$(date +%F_%H-%M-%S).sql
關鍵點:--single-transaction 僅對 InnoDB 有效;--master-data=2 輸出註釋形式 CHANGE MASTER TO ...,不加鎖;--flush-logs 產生新 Binlog,便於增量切割。
# 每小時/按業務頻率執行
mysqladmin -u$USER -p$PASS flush-logs
# 將產生的新 Binlog 文件 (如 mysql-bin.000027) 複製/同步到異地存儲
# 保留策略:全備保留 7 天,Binlog 保留 30 天或配合 expire_logs_days
恢復流程:全量 SQL 還原 → 依序應用增量 Binlog → 應用最新 Binlog 至故障點。
# Master 端執行 (不需 --flush-logs,避免多產生一個 Binlog)
mysqldump -u$USER -p$PASS \
--single-transaction \
--master-data=2 \
--routines \
--databases db1 db2 \
> /backup/for_slave_$(date +%F).sql
# 腳本傳輸到 Slave
scp /backup/for_slave_*.sql slave_host:/tmp/
# Slave 端導入
mysql -u$USER -p$PASS < /tmp/for_slave_*.sql
# 從備份文件頭部提取 CHANGE MASTER 信息
head -50 /tmp/for_slave_*.sql
# -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000010', MASTER_LOG_POS=809;
# Slave 配置並啟動復制
CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='repl_user',
MASTER_PASSWORD='repl_pass',
MASTER_LOG_FILE='mysql-bin.000010',
MASTER_LOG_POS=809;
START SLAVE;
SHOW SLAVE STATUS\G # 確認 Slave_IO_Running=Yes, Slave_SQL_Running=Yes
mysqldump --single-transaction --master-data=2 --routines --flush-logs --databases gs ngx_lua > gs_ngx_lua_backup.sqlhead -50 backup.sql 獲取 MASTER_LOG_FILE='mysql-bin.000027',將 000027 之前的 Binlog 移至安全區,執行 PURGE BINARY LOGS TO 'mysql-bin.000027' 更新索引 (實際文件已移走)。datadir,killall mysqld,重新初始化 mysql_install_db,mysql_secure_installation 設置密碼。mysql -uroot -p < gs_ngx_lua_backup.sqlmysqlbinlog mysql-bin.000027 > 27.sql && mysql -uroot -p < 27.sql
mysqlbinlog mysql-bin.000028 > 28.sql && mysql -uroot -p < 28.sql
datadir 前的最新狀態。--add-drop-table 默認開啟:導入腳本會先 DROP TABLE,若誤執行導致數據丟失。建議常態加 --skip-add-drop-table。--default-character-set 不一致導致亂碼。顯式指定或統一配置 [mysqldump] default-character-set=utf8mb4。--quick (默認開啟) 逐行讀取,避免一次性緩存整張表。--events 額外備份 Event。| 場景 | 標準命令模板 |
|---|---|
| 日常全備 | mysqldump --single-transaction --master-data=2 --routines --flush-logs --databases db1 db2 > full.sql + 系統庫獨立備份 |
| 搭建 Slave | mysqldump --single-transaction --master-data=2 --routines --databases db1 db2 > for_slave.sql (無需 --flush-logs) |
| PITR 恢復 | 全量 SQL 還原 → mysqlbinlog 依序轉換增量 Binlog → 執行 SQL |
大規模庫 (>500G) 推薦改用 xtrabackup 物理備份,速度快數倍、不阻塞、支持增量備份、恢復時間可控。