🔖
MySQLでデータの差分を取りたい その1
前提
- 業務を行っていて、処理の前後でどのテーブルのデータが書き換わったかを知りたかった
- 過去にはmysqldbcompareというツールがあった様子だが、2023年時点では古くなっている(動作させる事を諦めた)
概要・使い方
- スクリプトを実行し、システムのDBをdb_1にダンプする
- 何らかの処理を行う
- スクリプトを実行し、db_1をdb_2に、システムのDBをdb_1にダンプする
- 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
なんか便利そう。
タンプを取るってことは処理速度はデータベースのデータ量に依存しますか?
試してはいませんが、データ量が増えると時間が掛かるはずです
ちなみに普段はデータ量がかなり少ない開発用のDB比較に使っていますが、それでも数秒かかってしまいます…