はじめに
「数日前のあの時、本当にデータが更新されたのか?」
こうした調査が突然必要になることは、運用現場では珍しくありません。
MySQLのデフォルト設定では、実行済みSQLの全履歴は保存されません。
しかし、バイナリログ(Binary Log) が有効になっていれば、過去に実行された UPDATE / DELETE などの変更操作を遡って確認することが可能です。
本記事では、Linux環境のMySQLにおいて、
バイナリログから特定日時に実行された UPDATE 文を抽出・解析した手順をまとめます。
1. 調査の前提条件
まず、MySQLにログインし、ログの記録設定を確認します。
-- 全実行履歴(General Log)の確認
SHOW VARIABLES LIKE 'general_log%';
-- 変更履歴(Binary Log)の確認
SHOW VARIABLES LIKE 'log_bin%';
-
general_logが OFF でも、log_binが ON であれば
データの変更履歴(UPDATE / DELETE / INSERT)を追跡できます。
2. バイナリログの保存期間を確認する
バイナリログは無期限に保存されるわけではなく、
設定された保持期間を過ぎると自動的に削除されます。
まず、保持期間を確認します。
SHOW VARIABLES LIKE 'expire_logs_days';
-- 例:14 であれば、過去14日分の変更履歴が保持される
次に、現在存在するバイナリログファイルの一覧を確認します。
SHOW BINARY LOGS;
調査対象日時のログファイルが残っていることを、ここで必ず確認します。
3. mysqlbinlog コマンドによる詳細調査
バイナリログはバイナリ形式のため、そのままでは内容を確認できません。
MySQLが提供する専用ツール mysqlbinlog を使用して、テキスト形式に変換します。
指定した日時の UPDATE 文を抽出する
以下は、特定の日付(例:2026-01-30)に実行された UPDATE 文を抽出する例です。
sudo mysqlbinlog \
--start-datetime="2026-01-30 00:00:00" \
--stop-datetime="2026-01-30 23:59:59" \
--base64-output=DECODE-ROWS -v \
/var/lib/mysql/mysql-bin.000XXX \
| grep -i "UPDATE" -B 5
-
--base64-output=DECODE-ROWS -v
行ベース(ROW形式)のバイナリログを、人間が読める疑似SQL形式に変換するための必須オプション -
-B 5
実行日時などのメタ情報を確認するため、該当行の直前も表示する
4. 実行結果の解析
抽出されたログから、以下の情報を読み取ります。
実行タイミングの特定
#260130 16:32:11 server id 1 end_log_pos 26881590
### UPDATE `db_name`.`table_name`
#260130 16:32:11 は
2026年1月30日 16時32分11秒 に実行されたことを示しています。
更新内容の解析
DECODE-ROWS オプションを指定しているため、
更新前後の値が以下のように確認できます。
-
### WHERE
どの行が対象か(例:@1=10→ 1番目のカラムが 10 の行) -
### SET
どのカラムが、どの値に更新されたか
また、データ中に \x0d\x0a が含まれている場合、
これは CRLF(改行コード) を意味します。
このことから、
テキストエリアなど、改行を含む入力値による更新であった可能性も推測できます。
まとめ
- mysqldump は「ある時点の状態」を取得するためのもので、実行履歴は保持しない
- バイナリログ を活用することで、過去の「更新操作の証跡」を確認できる
- ログ保持期間(
expire_logs_days)を把握し、
消える前にエビデンスを確保することが重要
参考資料
- MySQL公式リファレンス
mysqlbinlog — バイナリログファイルを処理するためのユーティリティ
https://dev.mysql.com/doc/refman/8.0/ja/mysqlbinlog.html