デフォルトの mysqldump 形式では、ダンプされた各レコードは、ダンプ ファイル (つまり、sql ファイル) 内に個別の INSERT コマンドをそれぞれ独自の行に生成します。これはソース管理 (例: svn、git など) に最適です。これにより、差分とデルタの解決がより細かくなり、最終的にはより効率的なソース管理プロセスが実現します。ただし、非常に大きなサイズのテーブルの場合、これらすべての INSERT クエリを実行すると、SQL ファイルからの復元が非常に遅くなる可能性があります。
--extended-insert オプションを使用すると、ダンプされた sql ファイルの単一行ですべてのレコードを単一の INSERT コマンドにラップすることで、複数の INSERT の問題が修正されます。ただし、ソース管理プロセスは非常に非効率になります。テーブルの内容全体は sql ファイルの 1 行で表され、そのテーブルのどこかで 1 文字が変更されると、ソース管理は行全体 (テーブル全体) にバージョン間の差分としてフラグを立てます。また、大きなテーブルの場合、正式なソース管理システムを使用するメリットの多くが失われます。
したがって、理想的には、データベースを効率的に復元するために、SQL ファイルで、各テーブルを 1 つの INSERT で表す必要があります。効率的なソース管理プロセスのために、SQL ファイルでは、その INSERT コマンドの各レコードをそれぞれの行に配置する必要があります。
これに対する私の解決策は、次のバックアップ スクリプトです。
#!/bin/bash
cd my_git_directory/
ARGS="--host=myhostname --user=myusername --password=mypassword --opt --skip-dump-date"
/usr/bin/mysqldump $ARGS --database mydatabase | sed 's$VALUES ($VALUES\n($g' | sed 's$),($),\n($g' > mydatabase.sql
git fetch origin master
git merge origin/master
git add mydatabase.sql
git commit -m "Daily backup."
git push origin master
結果は、次のような SQL ファイルの INSERT コマンド形式になります。
INSERT INTO `mytable` VALUES
(r1c1value, r1c2value, r1c3value),
(r2c1value, r2c2value, r2c3value),
(r3c1value, r3c2value, r3c3value);
いくつかのメモ:
- コマンドラインのパスワード...私は知っていますが、安全ではなく、別の議論です。
- --opt: 特に --extended-insert オプションをオンにします (つまり、テーブルごとに 1 つの INSERT)。
- --skip-dump-date: mysqldump は通常、SQL ファイルの作成時に日付/時刻スタンプを挿入します。バージョン間の唯一の差分がその日付/時刻スタンプである場合、これはソース管理で厄介になる可能性があります。OS とソース管理システムは、ファイルとバージョンに日付/時刻のスタンプを付けます。SQLファイルでは実際には必要ありません。
- git コマンドは基本的な質問 (SQL ファイルのフォーマット) の中心ではありませんが、SQL ファイルをソース管理に戻す方法を示しています。同様のことが svn で実行できます。この sql ファイル形式を選択したソース管理と組み合わせると、ユーザーが作業コピーを更新するときに、インターネット上でデルタ (つまり、変更されたレコード) を移動するだけでよく、diff ユーティリティを利用できることがわかります。データベース内のどのレコードが変更されたかを簡単に確認できます。
- リモート サーバーに存在するデータベースをダンプする場合は、可能であれば、そのサーバーでこのスクリプトを実行して、各ダンプでネットワーク全体にデータベースの内容全体をプッシュしないようにします。
- 可能であれば、このスクリプトを実行しているのと同じサーバー上に、SQL ファイル用の作業ソース管理リポジトリを確立します。そこからリポジトリにチェックインします。これにより、ダンプのたびにネットワーク全体にデータベース全体をプッシュする必要がなくなります。