首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 數據被惡意篡改?實戰演練:從庫備份 + 主庫 Binlog 精準時間點恢復

     編輯:MySQL 資料庫相關知識

案例背景

2014-09-26 清晨,開發報告:文章表 content 字段被批量篡改為同一篇游記內容。日志定位攻擊時間:**2014-09-25 21:53:57**。架構:主庫雙實例,從庫每日冷備份,主庫 Binlog 保留 7 天。

恢復策略:基於時間點的不完全恢復(PITR)

  1. 從庫調取 **2014-09-23 18:19:12** 開始的冷備份(Stop Slave 時刻,主從延遲 0)
  2. 主庫提取 **2014-09-23 18:19:12 → 2014-09-25 21:53:56** 的 Binlog 重放
  3. 攻擊後數據(21:53:57 之後)業務確認可捨棄,後續人工補齊

關鍵時間點確認

節點時間依據
備份開始(Stop Slave)2014-09-23 18:19:12備份腳本日志 + 目錄修改時間
備份結束2014-09-23 18:33:00目錄時間戳
攻擊發生2014-09-25 21:53:57應用日志/審計日志
恢復截止2014-09-25 21:53:56攻擊前 1 秒

關鍵判斷: 從庫備份反映的是 **Stop Slave 那一刻(18:19:12)** 的一致性快照,而非備份結束時間。

實操步驟詳解

1. 從備份機拉取備份文件

scp backup_host:/data/mysqlbak/20140923/20140923.db_name.gz recovery_host:/data/opdir/20140926/

2. 恢復測試機解壓導入

gunzip 20140923.db_name.gz
mysql -uroot -pxxx -S /tmp/mysql.sock < 20140923.db_name

3. 從主庫拉取所需 Binlog 文件

# 主庫 Binlog 列表
-rw-rw---- 1 mysql mysql 37425262 Sep 24 00:00 mysql-bin.000472
-rw-rw---- 1 mysql mysql 137389819 Sep 25 00:00 mysql-bin.000473
-rw-rw---- 1 mysql mysql 147386521 Sep 26 00:00 mysql-bin.000474

# 需要 472, 473, 474 三個文件(覆蓋 18:19 → 21:53)
scp mysql-bin.00047[2-4] recovery_host:/data/opdir/20140926/

4. mysqlbinlog 按時間區間導出 SQL

mysqlbinlog --database=db_name \
  --start-datetime='2014-09-23 18:19:12' \
  --stop-datetime='2014-09-25 21:53:56' \
  mysql-bin.000472 > 472.sql

mysqlbinlog --database=db_name \
  --start-datetime='2014-09-23 18:19:12' \
  --stop-datetime='2014-09-25 21:53:56' \
  mysql-bin.000473 > 473.sql

mysqlbinlog --database=db_name \
  --start-datetime='2014-09-23 18:19:12' \
  --stop-datetime='2014-09-25 21:53:56' \
  mysql-bin.000474 > 474.sql

5. 依序導入 Binlog SQL

mysql -uroot -pxxx -S /tmp/mysql.sock db_name < 472.sql
mysql -uroot -pxxx -S /tmp/mysql.sock db_name < 473.sql
mysql -uroot -pxxx -S /tmp/mysql.sock db_name < 474.sql

6. 驗證數據正確性

mysql> SELECT MAX(createtime), MAX(updatetime) FROM table_name;
+-----------------+-----------------+
| max(createtime) | max(updatetime) |
+-----------------+-----------------+
|      1411648043 |      1411648043 |  -- 約 20:27,早於攻擊時間
+-----------------+-----------------+

業務方核對關鍵表數據無誤後,導出目標表:

mysqldump -uroot -pxxx -S /tmp/mysql.sock -q db_name table_name > table_name.sql
gzip table_name.sql
scp table_name.sql.gz master_host:/data/recovery/

7. 線上主庫切換數據(風險最小化)

-- A. 重命名原表(保留現場,不直接 DROP)
RENAME TABLE table_name TO old_table_name;

-- B. 導入恢復數據
gunzip table_name.sql.gz
mysql -uroot -pxxx -S /tmp/mysql.sock db_name < table_name.sql

業務驗證通過後,啟動應用;觀察無異常後再清理 old_table_name。

核心經驗總結

  • 備份時間點以 Stop Slave 為準,而非腳本開始/結束時間
  • Binlog 導出必須指定 --database,避免跨庫干擾
  • 恢復鏈路要在隔離環境先跑通,驗證無誤再上線
  • 線上切換用 RENAME 不用 DROP,保留回滾通道
  • 平時演練 PITR 流程,真刀實槍才不慌
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved