使用默认的 mysqldump 格式,转储的每条记录都会在转储文件(即 sql 文件)中生成一个单独的 INSERT 命令,每个命令都在自己的行中。这非常适合源代码控制(例如,svn、git 等),因为它使 diff 和 delta 分辨率更精细,并最终导致更有效的源代码控制过程。但是,对于非常大的表,执行所有这些 INSERT 查询可能会使从 sql 文件恢复的速度非常慢。
使用 --extended-insert 选项通过将所有记录包装到转储 sql 文件的单行上的单个 INSERT 命令中来修复多个 INSERT 问题。但是,源代码控制过程变得非常低效。整个表的内容在 sql 文件中的单行中表示,如果该表中的任何一个字符发生了变化,源代码控制会将整行(即整个表)标记为版本之间的差异。而且,对于大型表,这抵消了使用正式源代码控制系统的许多好处。
所以理想情况下,为了高效的数据库恢复,在 sql 文件中,我们希望每个表都由单个 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 选项(即,每个表一个 INSERT)。
- --skip-dump-date:mysqldump 通常在创建时将日期/时间戳记在 sql 文件中。当版本之间的唯一差异是该日期/时间戳时,这在源代码控制中可能会变得很烦人。操作系统和源代码控制系统将为文件和版本添加日期/时间戳。它在 sql 文件中并不真正需要。
- git 命令不是基本问题(格式化 sql 文件)的核心,但显示了我如何将我的 sql 文件恢复到源代码控制中,类似的事情可以用 svn 完成。当将此 sql 文件格式与您选择的源代码控制相结合时,您会发现当您的用户更新他们的工作副本时,他们只需在 Internet 上移动增量(即更改的记录),他们可以利用 diff 实用程序轻松查看数据库中的哪些记录已更改。
- 如果您要转储驻留在远程服务器上的数据库,如果可能,请在该服务器上运行此脚本以避免每次转储时通过网络推送数据库的全部内容。
- 如果可能,在您运行此脚本的同一台服务器上为您的 sql 文件建立一个工作源代码控制存储库;从那里将它们签入存储库。这也将有助于避免每次转储时都必须通过网络推送整个数据库。