🔖

MySQLでデータの差分を取りたい その1

2023/08/08に公開2

前提

  • 業務を行っていて、処理の前後でどのテーブルのデータが書き換わったかを知りたかった
  • 過去にはmysqldbcompareというツールがあった様子だが、2023年時点では古くなっている(動作させる事を諦めた)

概要・使い方

  1. スクリプトを実行し、システムのDBをdb_1にダンプする
  2. 何らかの処理を行う
  3. スクリプトを実行し、db_1をdb_2に、システムのDBをdb_1にダンプする
  4. db_1とdb_2のchecksumを比較

実現方法

比較用のdockerコンテナ作成

  • MySQLのバージョンは8.0以降を使う。5.7でjson型の属性があると、データが同じでもchecksumが変わってしまうため。
  • 動作させたMySQLで「db_1」「db_2」データベースを作成しておく。中身は空でOK。
  • 諸々の設定はシステムのDBに合わせておく

ダンプ取得&checksum比較スクリプト

実行前に./dump/dbフォルダを作成しておく

#!/bin/zsh

DOCKER_CONTAINER=比較用dockerコンテナのID

cd ./dump/db

echo '### db_1 -> db_2'
docker exec $DOCKER_CONTAINER sh -c "mysqldump db_1 --set-gtid-purged=OFF | mysql db_2"

echo '### システムのDB -> db_1'
mysqldump --single-transaction -h 127.0.0.1 システムのDB名 --set-gtid-purged=OFF --column-statistics=0 > inspect.dump
docker exec -i $DOCKER_CONTAINER mysql -u root db_1 < inspect.dump


echo '### checksum'
docker exec -it $DOCKER_CONTAINER mysql -u root db_1 -e"checksum table 全テーブル名をカンマで繋いだ文字列 extended" > db1_checksum
docker exec -it $DOCKER_CONTAINER mysql -u root db_2 -e"checksum table 全テーブル名をカンマで繋いだ文字列 extended" > db2_checksum

echo '### diff'
diff db1_checksum <(sed -e 's/db_2/db_1/g' ./db2_checksum)

結果

こんな感じで、変更があったテーブルの一覧が出力されます(テーブル名は隠しています)

コミューン株式会社

Discussion

anoChickanoChick

なんか便利そう。
タンプを取るってことは処理速度はデータベースのデータ量に依存しますか?

もろきゅうもろきゅう

データ量に依存

試してはいませんが、データ量が増えると時間が掛かるはずです
ちなみに普段はデータ量がかなり少ない開発用のDB比較に使っていますが、それでも数秒かかってしまいます…