學(xué)會(huì)MySQL數(shù)據(jù)備份與恢復(fù),刪庫不跑路!

2020年2月,某上市公司運(yùn)維人員因糾紛手動(dòng)執(zhí)行rm -rf /*,直接導(dǎo)致市值蒸發(fā)超10億。
2022年5月,某電商平臺(tái)因未配置備庫,主庫故障后宕機(jī)11小時(shí),損失千萬訂單。
這些真實(shí)案例告訴我們:沒有安全的數(shù)據(jù)庫,就像沒有安全繩的走鋼絲——一次誤操作就可能讓業(yè)務(wù)墜入深淵。
在實(shí)際的運(yùn)維過程中,做好數(shù)據(jù)庫的備份和恢復(fù)至關(guān)重要,也是運(yùn)維工程師和dba需要掌握的基本技能。

一、數(shù)據(jù)庫需要哪些“后悔藥”?
- ? 冷備份(需停庫):直接對(duì)數(shù)據(jù)庫數(shù)據(jù)目錄文件進(jìn)行
tar歸檔。 - ? 熱備份:使用
mysqldump或XtraBackup進(jìn)行在線備份。 - ? 增量備份:基于 binlog 或者 InnoDB 事務(wù)日志進(jìn)行數(shù)據(jù)恢復(fù)。
1. 全量備份:整庫的存檔快照
邏輯備份:mysqldump(適合中小型數(shù)據(jù)庫)
# 導(dǎo)出整個(gè)數(shù)據(jù)庫
mysqldump -u root -p --all-databases > full_backup.sql優(yōu)點(diǎn):跨版本兼容,單個(gè) SQL 文件易于管理
缺點(diǎn):恢復(fù)速度較慢,備份文件較大
需停機(jī):否
物理備份:XtraBackup(適合大規(guī)模數(shù)據(jù)庫)
# 全量備份
xtrabackup --backup --user=root --password=123456 --target-dir=/backups/full優(yōu)點(diǎn):恢復(fù)速度快,適合 TB 級(jí)數(shù)據(jù)庫
缺點(diǎn):需與 MySQL 版本嚴(yán)格匹配
需停機(jī):否(支持熱備)
物理備份:Tar冷備(適合低頻備份和遷移)
# 停庫保障一致性(需停機(jī)?。?systemctl stop mysql
tar -czvf /backups/mysql_$(date +%F).tar.gz /var/lib/mysql/*
systemctl start mysql優(yōu)點(diǎn):簡(jiǎn)單直觀,操作簡(jiǎn)單,適合小型數(shù)據(jù)庫或臨時(shí)備份
缺點(diǎn):必須停機(jī),否則數(shù)據(jù)可能不一致
需停機(jī):是
2. 增量備份:只存“變化量”的智能方案
依賴 binlog 日志(記錄所有數(shù)據(jù)變更):
# 導(dǎo)出某時(shí)間點(diǎn)后的 binlog
mysqlbinlog --start-datetime="2024-01-01 00:00:00" mysql-bin.000001 > incr_backup.sql優(yōu)點(diǎn):節(jié)省空間,可精確恢復(fù)到秒級(jí)
缺點(diǎn):恢復(fù)流程復(fù)雜,需結(jié)合全量備份
需停機(jī):否
二、數(shù)據(jù)備份方案怎么選?
備份類型 | 速度 | 恢復(fù)難度 | 適用場(chǎng)景 | 代表工具 | 是否需停機(jī) |
邏輯全備 | 慢 | 簡(jiǎn)單 | 小數(shù)據(jù)量,跨版本遷移 | mysqldump | 否 |
物理全備 | 快 | 中等 | 大數(shù)據(jù)量,快速恢復(fù) | XtraBackup | 否 |
binlog 增量 | 極快 | 復(fù)雜 | 需精確到時(shí)間點(diǎn)的恢復(fù) | mysqlbinlog | 否 |
Tar 冷備 | 中等 | 簡(jiǎn)單 | 停機(jī)情況下的完整備份 | tar | 是 |
快照備份 | 最快 | 簡(jiǎn)單 | 云服務(wù)器 + 大容量存儲(chǔ) | LVM/云磁盤快照 | 否 |
黃金法則:
- 中小項(xiàng)目:每周全備 + 每日 binlog 增量
- 大型系統(tǒng):物理全備(XtraBackup)+ 每小時(shí) binlog
- 致命操作前:臨時(shí)表級(jí)備份(如 ALTER TABLE 前)
三、XtraBackup:TB級(jí)數(shù)據(jù)庫的“救世主”
1. 為什么選擇 XtraBackup?
- 熱備份:備份期間數(shù)據(jù)庫正常讀寫,業(yè)務(wù)無感知
- 增量備份:僅備份變化的數(shù)據(jù)塊,節(jié)省時(shí)間和空間
- 支持壓縮加密:邊備份邊壓縮,直傳云端存儲(chǔ)
2. 核心操作(以 MySQL 8.0 為例)
# 全量備份
xtrabackup --backup --user=root --password=123456 --target-dir=/backups/full
# 增量備份(基于上一次備份)
xtrabackup --backup --target-dir=/backups/inc1 --incremental-basedir=/backups/full
# 恢復(fù)數(shù)據(jù)(合并增量到全量)
xtrabackup --prepare --apply-log-only --target-dir=/backups/full
xtrabackup --prepare --target-dir=/backups/full --incremental-dir=/backups/inc1四、如何避免數(shù)據(jù)災(zāi)難?
1. 誤刪數(shù)據(jù)恢復(fù)
mysql -u root -p < full_backup.sql # 導(dǎo)入全量備份
mysqlbinlog binlog.000002 | mysql -u root -p # 追增量日志2. 突然斷電后的恢復(fù)
InnoDB 自動(dòng)恢復(fù):MySQL 重啟時(shí),通過 redo log 自動(dòng)回放未提交事務(wù)
手動(dòng)檢查:
mysqlcheck -u root -p --all-databases # 檢查所有表狀態(tài)五、防翻車指南:必須知道的 5 個(gè) Tips
- 備份驗(yàn)證:定期試恢復(fù)備份文件到測(cè)試環(huán)境
- binlog 必開:配置文件中確保有
log-bin=mysql-bin - 監(jiān)控告警:用 Prometheus 監(jiān)控備份任務(wù)是否成功
- 多副本存儲(chǔ):備份文件至少存 3 份(本地 + 異機(jī) + 云存儲(chǔ))
- 防刪庫大招:
-- 設(shè)置 sql_safe_updates 強(qiáng)制 WHERE 條件
SET sql_safe_updates=1;六、數(shù)據(jù)庫斷電恢復(fù)
如果數(shù)據(jù)庫沒有備份的情況下,可以嘗試如下方式恢復(fù)數(shù)據(jù),降低損失
1. innodb_force_recovery:數(shù)據(jù)崩潰后的急救方案
在數(shù)據(jù)庫異常崩潰或斷電后,InnoDB 數(shù)據(jù)文件可能損壞,導(dǎo)致 MySQL 無法啟動(dòng)。此時(shí),可借助 innodb_force_recovery 參數(shù)強(qiáng)制啟動(dòng) MySQL,并嘗試修復(fù)數(shù)據(jù)。
2. 使用場(chǎng)景
現(xiàn)象:MySQL 啟動(dòng)失敗,日志中出現(xiàn)如下錯(cuò)誤:
InnoDB: Database page corruption on disk or a failed file read
InnoDB: Crash recovery is in progress...適用情況:
- 斷電或強(qiáng)制關(guān)機(jī)導(dǎo)致 InnoDB 表損壞
- 數(shù)據(jù)文件(.ibd)損壞但未完全丟失
- 目標(biāo)是緊急啟動(dòng) MySQL,導(dǎo)出數(shù)據(jù)后重建數(shù)據(jù)庫
3.操作步驟
第 1 步:修改配置,啟用強(qiáng)制恢復(fù)模式
在 my.cnf 的 [mysqld] 段添加:
[mysqld]
innodb_force_recovery=1 # 從級(jí)別 1 開始嘗試第 2 步:逐級(jí)嘗試啟動(dòng)
innodb_force_recovery 取值范圍 1~6,數(shù)字越大,修復(fù)越激進(jìn)。
sudo systemctl restart mysql檢查日志,若仍無法啟動(dòng),則逐級(jí)提高 innodb_force_recovery 級(jí)別。
級(jí)別 | 含義 |
1 | 忽略損壞頁,嘗試讀取表 |
2 | 禁止后臺(tái)線程(如 purge 線程)運(yùn)行 |
3 | 不執(zhí)行事務(wù)回滾 |
4 | 禁止插入緩沖合并 |
5 | 不查看 Undo 日志 |
6 | 不執(zhí)行 redo 日志前滾 |
第 3 步:?jiǎn)?dòng)成功后緊急備份
mysqldump -u root -p --all-databases > emergency_backup.sql如果發(fā)現(xiàn)部分表損壞,可以使用mysqlcheck 檢查所有表的狀態(tài)
mysqlcheck -u root -p --all-databases # 檢查所有表狀態(tài)如果表損壞,可以使用'mysqlcheck'工具的'--repair'選項(xiàng)來修復(fù)表,
- MyISAM:支持
--repair直接修復(fù) - InnoDB:支持
--check進(jìn)行檢查,但修復(fù)需結(jié)合innodb_force_recovery
如果確認(rèn)損壞表為非關(guān)鍵表,導(dǎo)出數(shù)據(jù)庫時(shí)也可以加--ignore-table并跳過指定表
mysqldump -u username -p --ignore-table=database_name.table_name database_name > backup.sqlmysql命令行導(dǎo)出數(shù)據(jù)庫并跳過指定表
與其他類似工具相比,'mysqlcheck'是 MySQL 官方提供的工具,與 MySQL 數(shù)據(jù)庫緊密集成,具有更好的兼容性和可靠性。
第 4 步:重建數(shù)據(jù)庫
- 清空數(shù)據(jù)目錄
/var/lib/mysql - 重新初始化 MySQL
- 導(dǎo)入備份數(shù)據(jù)
注意事項(xiàng)
- 強(qiáng)制恢復(fù)模式下禁用寫操作,只能用于數(shù)據(jù)導(dǎo)出。
- 臨時(shí)方案,導(dǎo)出數(shù)據(jù)后應(yīng)關(guān)閉
innodb_force_recovery并重建數(shù)據(jù)庫。 - 可能丟失數(shù)據(jù),
innodb_force_recovery >= 4可能導(dǎo)致事務(wù)丟失。
實(shí)戰(zhàn)案例
場(chǎng)景:某電商數(shù)據(jù)庫因機(jī)房斷電無法啟動(dòng)。
- 設(shè)定
innodb_force_recovery=1,啟動(dòng)失敗。 - 設(shè)定
innodb_force_recovery=2,啟動(dòng)成功,但部分表無法訪問。 - 使用
mysqlcheck檢查表:
mysqlcheck -u root -p --all-databases --check --extended- 設(shè)定
預(yù)防措施
硬件層面:
- 使用 UPS 防止斷電。
- 啟用 RAID 10 保障磁盤冗余。
數(shù)據(jù)庫層面:
- 設(shè)置
innodb_flush_log_at_trx_commit=1,確保事務(wù)日志實(shí)時(shí)寫入。 - 定期執(zhí)行
CHECK TABLE檢測(cè)表健康狀態(tài)。
總結(jié)
innodb_force_recovery 是數(shù)據(jù)庫崩潰后的應(yīng)急方案,使用時(shí)需謹(jǐn)慎。真正的安全保障是 定期備份 + 備份恢復(fù)演練。
結(jié)論
小庫輕量級(jí):mysqldump + binlog
大庫高性能:XtraBackup + 快照
作死保護(hù):操作前手動(dòng)備份關(guān)鍵表
結(jié)合物理備份與二進(jìn)制日志,可實(shí)現(xiàn)任意時(shí)間點(diǎn)恢復(fù)(PITR):
- 每天凌晨 用 XtraBackup 做全量備份
- 每小時(shí) 采集一次 binlog 并上傳到云存儲(chǔ)
- 故障時(shí) 先用全量備份恢復(fù),再重放 binlog 到指定時(shí)間點(diǎn)






























