MySQL通過Binlog實(shí)現(xiàn)數(shù)據(jù)備份和恢復(fù)
一、 首先安裝MySQL
為了簡便操作,我使用docker進(jìn)行演示,docker安裝mysql的命令如下所示:
docker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=1234 \ -v ./mysql/data:/var/lib/mysql \ -v ./mysql/conf:/etc/mysql/conf.d \ -v ./mysql/init:/docker-entrypoint-initdb.d \ mysql:8.0
- 數(shù)據(jù)持久化:-v ./mysql/data:/var/lib/mysql 讓數(shù)據(jù)安全地留在了宿主機(jī)。
- 配置文件分離:-v ./mysql/conf:/etc/mysql/conf.d 讓你可以隨意改配置而不用進(jìn)容器。
- 初始化腳本:-v ./mysql/init:/docker-entrypoint-initdb.d ,你可以把 .sql 建表腳本放這里,容器首次啟動(dòng)會自動(dòng)執(zhí)行。
二、Binlog介紹
Binlog (Binary Log) 就是 MySQL 的“錄像機(jī)”。
它記錄了數(shù)據(jù)庫里所有的修改操作(比如增刪改),按時(shí)間順序排列。這就好比你把游戲里所有改變數(shù)據(jù)的操作都錄了下來,存成了一部連續(xù)的電影。
對你做游戲來說,Binlog 有兩個(gè)特別實(shí)用的用途:
(1)數(shù)據(jù)的“后悔藥”與“時(shí)間機(jī)器”
開發(fā)過程中難免會有誤操作,比如不小心執(zhí)行了一條 SQL 刪了測試服的用戶數(shù)據(jù)。
沒用 Binlog:數(shù)據(jù)可能就真沒了,或者只能從昨天凌晨的備份恢復(fù)(意味著今天的測試白干了)。
有了 Binlog:你可以拿著“錄像”快進(jìn)到出問題的時(shí)間點(diǎn),或者重放這幾分鐘的記錄,把數(shù)據(jù)精確恢復(fù)到誤操作前一秒。
(2)做“數(shù)據(jù)同步”的基石
最常見的需求。比如:
你有一個(gè)主庫(負(fù)責(zé)處理用戶的賬號、庫存、寫入數(shù)據(jù))。
你有一個(gè)從庫(專門負(fù)責(zé)給官網(wǎng)提供排行榜查詢、或者給后臺客服查詢數(shù)據(jù))。
為了讓從庫的數(shù)據(jù)和主庫一模一樣,MySQL 就是利用 Binlog 把主庫的“錄像”同步給從庫,讓從庫照著做一遍。
新手建議:
剛開始做項(xiàng)目時(shí),如果你不會手寫腳本來解析 Binlog,但一定要確保你的云數(shù)據(jù)庫(比如阿里云 RDS 或騰訊云 MySQL)開啟了 Binlog 功能,并且設(shè)置了合理的保留時(shí)間(比如保留 7 天)。這樣即使出問題,運(yùn)維人員也能幫你把數(shù)據(jù)救回來。
三、開啟Binlog(數(shù)據(jù)備份)
3.1 查找mysql文件
首先,找到mysql的配置文件,如果忘了放哪了,直接讓 Linux 幫你找,直接全局搜索(最暴力,推薦)
find / -name "mysql" -type d 2>/dev/null
這條命令會從根目錄開始找名字叫 mysql 的文件夾。

如果看到路徑像 /root/mysql、/home/user/mysql 這樣的,大概率就是它了。
(注意:它會搜到系統(tǒng)自帶的 /var/lib/mysql,那個(gè)是系統(tǒng)的,不是你的,別搞混了,找?guī)ё远x路徑特征的)
找到正確的路徑后(比如是在 /root/mysql),以后的操作都要帶上這個(gè)絕對路徑
進(jìn)入目錄
cd /root/mysql # 換成你 find 出來的真實(shí)路徑
檢查一下目錄結(jié)構(gòu)(確認(rèn)無誤)
你應(yīng)該能看到 data、conf、init 這三個(gè)文件夾。
ls -l
查看數(shù)據(jù)目錄
ls -l ./data/
3.2 開啟binlog
查看配置目錄
ls -l ./conf

沒問題!這很正常,說明你的 conf 文件夾目前是空的。
現(xiàn)在我們就在這個(gè)空文件夾里創(chuàng)建配置文件。請保持在 /root/mysql 目錄下,直接復(fù)制并執(zhí)行下面這段命令:
cat > ./conf/my.cnf << EOF [mysqld] # 開啟 Binlog log-bin=mysql-bin # 服務(wù)器 ID (隨便設(shè)個(gè)唯一數(shù)字) server-id=1 # 設(shè)置 Binlog 格式為 ROW (恢復(fù)數(shù)據(jù)最推薦) binlog_format=ROW # 日志保留 7 天,自動(dòng)清理防止占滿磁盤 expire_logs_days=7 # --- 核心配置:中文支持 --- character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci EOF
執(zhí)行完這一步后,再檢查一下:
ls -l ./conf

3.3 重啟生效
重啟容器讓配置生效:
docker restart mysql
等容器重啟完,你的 Binlog 功能就已經(jīng)啟動(dòng)了!隨后你可以在 ./data 目錄里看到對應(yīng)的日志文件生成。
四、通過Binlog實(shí)現(xiàn)數(shù)據(jù)恢復(fù)
4.1 數(shù)據(jù)恢復(fù)前準(zhǔn)備,故意制造數(shù)據(jù)丟失
為了演示,我需要?jiǎng)?chuàng)建一張數(shù)據(jù)庫表
我們就以 test_db 數(shù)據(jù)庫和 tb_user 表為例。這是一個(gè)非常標(biāo)準(zhǔn)的實(shí)戰(zhàn)演練
登錄 MySQL
docker exec -it mysql mysql -uroot -p1234
建庫建表并插入初始數(shù)據(jù)
CREATE DATABASE test_db;
USE test_db;
-- 創(chuàng)建用戶表
CREATE TABLE tb_user (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用戶ID',
username VARCHAR(50) COMMENT '用戶名',
role VARCHAR(50) COMMENT '角色'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶表';
-- 插入兩個(gè)初始用戶
INSERT INTO tb_user (username, role) VALUES ('張三', '程序員');
INSERT INTO tb_user (username, role) VALUES ('李四', '醫(yī)生');
-- 查看當(dāng)前數(shù)據(jù)
SELECT * FROM tb_user;
此時(shí)應(yīng)該有兩行數(shù)據(jù)。
模擬誤操作(刪表)
-- 災(zāi)難發(fā)生:誤刪了用戶表 DROP TABLE tb_user; -- 確認(rèn)數(shù)據(jù)已丟失 SHOW TABLES;
4.2 開始恢復(fù)數(shù)據(jù)
現(xiàn)在 test_db 里空空如也。接下來我們打開一個(gè)新的終端窗口(或者按 Ctrl+C 退出當(dāng)前 MySQL 會話),開始在 Linux 命令行進(jìn)行恢復(fù)。
查看當(dāng)前的 Binlog 日志文件
ls -lh /root/mysql/data/
有新日志生成: mysql-bin.000001剛剛生成,說明你剛才所有的刪表、建表、插入數(shù)據(jù)的操作,都被忠實(shí)地記錄在這個(gè)小文件里了。
文件夾 test_db:這是你剛才創(chuàng)建的數(shù)據(jù)庫目錄,里面的 .ibd 文件就是真正的數(shù)據(jù)文件。
4.3 分析日志,找到誤刪的“案發(fā)時(shí)間點(diǎn)”
我們需要用到mysqlbinlog,那么簡單介紹一下mysqlbinlog
mysqlbinlog 是一個(gè)獨(dú)立的工具程序,并不包含在基礎(chǔ)的 mysql 鏡像里。你現(xiàn)在的鏡像里只有數(shù)據(jù)庫服務(wù)端(mysqld)和客戶端(mysql),沒有解析日志的工具(mysqlbinlog)。
這就像你買了一臺電視機(jī)(數(shù)據(jù)庫服務(wù)),它只能放電視,但它沒有“錄像機(jī)編輯功能”(日志工具),那個(gè)得單獨(dú)買。
# 1. 安裝官方源 yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-11.noarch.rpm # 2. 安裝 8.0 客戶端 yum install mysql-community-client -y
檢查是否安裝成功
mysqlbinlog --version
查看日志(定位誤刪位置)
# 直接讀宿主機(jī)文件,不要進(jìn) docker mysqlbinlog --no-defaults /root/mysql/data/binlog.000001 | tail -n 30
先確認(rèn) MySQL 的真實(shí)數(shù)據(jù)目錄和 binlog 文件位置
先登錄 MySQL 客戶端
docker exec -it mysql mysql -uroot -p1234
登錄后執(zhí)行以下 SQL,查看 binlog 文件的真實(shí)存儲路徑和文件列表:
-- 查看 binlog 文件列表(能看到的才是真實(shí)存在的) show binary logs; -- 查看binlog配置 SHOW VARIABLES LIKE 'log_bin%'; SHOW VARIABLES LIKE 'binlog_format%'; -- 查看 MySQL 的數(shù)據(jù)目錄(binlog 默認(rèn)存在這個(gè)目錄下) show variables like 'datadir';
4.4 恢復(fù)數(shù)據(jù)
因?yàn)槲耶?dāng)前在mysql目錄中,所以我使用相對路徑./data/mysql-bin.000001指定該日志文件哦!
查看日志文件
mysqlbinlog -v ./data/mysql-bin.000001

4.4.1 指定位置點(diǎn)恢復(fù)
有兩個(gè)參數(shù)填寫,一個(gè)是開始位置點(diǎn),一個(gè)是結(jié)束位置點(diǎn)。如上圖的at就是點(diǎn)位
# at 1008 ← 第一個(gè)事務(wù)開始 # at 1086 ← BEGIN # at 1151 ← INSERT操作 # at 1193 ← INSERT結(jié)束 # at 1224 ← COMMIT完成 # at 1301 ← DROP TABLE開始
DELETE/DROP語句在位置 1301
有用的數(shù)據(jù)在位置 1008-1224
# 指定位置點(diǎn)
mysqlbinlog --start-position=107 \
--stop-position=1000 \
./data/mysql-bin.000001 --skip-gtids | docker exec -i mysql mysql -uroot -p1234
如果只恢復(fù)單個(gè)操作
# 提取第一個(gè)完整事務(wù)(1008到1224之間的INSERT操作)
mysqlbinlog --start-position=1008 \
--stop-position=1224 \
./data/mysql-bin.000001 --skip-gtids | docker exec -i mysql mysql -uroot -p1234
提取到DROP之前的所有內(nèi)容
# 提取從開始到DROP之前的所有操作
mysqlbinlog --start-position=154 \
--stop-position=1301 \
./data/mysql-bin.000001 --skip-gtids | docker exec -i mysql mysql -uroot -p1234提取到DROP之前的所有內(nèi)容
# 提取整個(gè)文件,但跳過DROP語句
mysqlbinlog --start-position=154 \
--stop-position=1300 \
./data/mysql-bin.000001 --skip-gtids | docker exec -i mysql mysql -uroot -p12344.4.2 指定時(shí)間區(qū)域恢復(fù)
有兩個(gè)參數(shù)填寫,一個(gè)是開始時(shí)間,一個(gè)是結(jié)束時(shí)間。如果有備份的話,最好回復(fù)數(shù)據(jù)可以填寫最后一次備份的結(jié)束時(shí)間。
#提取刪除前的所有操作(從表創(chuàng)建到刪除)
mysqlbinlog --start-datetime="2026-01-14 14:00:00" \
--stop-datetime="2026-01-14 14:19:55" \
./data/mysql-bin.000001 --skip-gtids | docker exec -i mysql mysql -uroot -p1234
執(zhí)行命令后可以發(fā)現(xiàn)我們的數(shù)據(jù)庫恢復(fù)咯!
以上就是MySQL通過Binlog實(shí)現(xiàn)數(shù)據(jù)備份和恢復(fù)的詳細(xì)內(nèi)容,更多關(guān)于MySQL Binlog數(shù)據(jù)備份和恢復(fù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在Windows環(huán)境下使用MySQL:實(shí)現(xiàn)自動(dòng)定時(shí)備份
下面小編就為大家分享一篇在Windows環(huán)境下使用MySQL:實(shí)現(xiàn)自動(dòng)定時(shí)備份的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
MySQL group by對單字分組序和多字段分組的方法講解
今天小編就為大家分享一篇關(guān)于MySQL group by對單字分組序和多字段分組的方法講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
MySQL的兩種分頁方式之Offset/Limit分頁和游標(biāo)分頁詳解
這篇文章主要對比了MySQL的Offset/Limit分頁與游標(biāo)分頁,指出前者簡單但存在數(shù)據(jù)漂移和性能缺陷,后者通過游標(biāo)避免這些問題且更高效,建議根據(jù)業(yè)務(wù)場景選擇分頁方式,深度分頁或動(dòng)態(tài)數(shù)據(jù)宜用游標(biāo)分頁,而延遲聯(lián)結(jié)可優(yōu)化Offset/Limit性能,需要的朋友可以參考下2025-09-09
MySQL慢查詢?nèi)罩緩呐渲玫絻?yōu)化實(shí)踐全解析
慢查詢?nèi)罩臼荕ySQL性能優(yōu)化的關(guān)鍵工具,記錄執(zhí)行時(shí)間超過閾值的SQL語句,幫助定位性能瓶頸和優(yōu)化SQL,本文介紹MySQL慢查詢?nèi)罩緩呐渲玫絻?yōu)化實(shí)踐全解析,感興趣的朋友跟隨小編一起看看吧2026-01-01

