使用crontab创建MySQL数据库压缩文件的正确方法——mysqldump和gzip命令

114

我在使用crontab时遇到了问题。我想要自动备份MySQL数据库。

环境:

  • Debian GNU/Linux 7.3 (wheezy)
  • MySQL Server version: 5.5.33-0+wheezy1(Debian)
  • 用户、备份和备份2目录的权限为755
  • MySQL数据库和Debian帐户的用户名相同

从Shell中,这个命令可以工作。

mysqldump -u user -p[user_password] [database_name] | gzip > dumpfilename.sql.gz
当我使用crontab -e将其放置在cron表中时。
* * /usr/bin/mysqldump -u user -pupasswd mydatabase | gzip> /home/user/backup/mydatabase-backup-`date +\%m\%d_\%Y`.sql.gz >/dev/null 2>&1

每分钟在 /home/user/backup 目录下创建一个文件,但大小为0字节。

然而,当我将此输出重定向到第二个目录 backup2 时,我注意到正确的 mysqldump 压缩文件已在其中创建。我无法弄清楚我的错误是什么,导致第一个目录中出现了 0 字节文件,而第二个目录中出现了预期的输出。

* * /usr/bin/mysqldump -u user -pupasswd my-database | gzip> /home/user/backup/mydatabase-backup-`date +\%m\%d_\%Y`.sql.gz >/home/user/backup2/mydatabase-backup-`date +\%m\%d_\%Y`.sql.gz 2>&1

我非常希望能够得到一个解释。

谢谢


抱歉第一行代码中打错了,应该是gzip而不是zip。 - user3397547
我不会每分钟运行这个。 - m79lkm
1
我只是运行它来测试命令。 - user3397547
5个回答

143

首先执行mysqldump命令,并使用管道重定向生成的输出。 管道将标准输出作为标准输入发送到gzip命令。 在filename.gz之后,是输出重定向运算符(>),该运算符将继续重定向数据直到最后一个文件名,数据将保存在那里。

例如,此命令将转储数据库并通过gzip运行,最终数据将落在three.gz中。

mysqldump -u user -pupasswd my-database | gzip > one.gz > two.gz > three.gz

$> ls -l
-rw-r--r--  1 uname  grp     0 Mar  9 00:37 one.gz
-rw-r--r--  1 uname  grp  1246 Mar  9 00:37 three.gz
-rw-r--r--  1 uname  grp     0 Mar  9 00:37 two.gz

我的原始回答是将数据库转储重定向到多个压缩文件的示例(不需要双重压缩)。 (由于我匆忙扫描问题,严重错过了 - 对此感到抱歉)

这是重新压缩文件的示例:

mysqldump -u user -pupasswd my-database | gzip -c > one.gz; gzip -c one.gz > two.gz; gzip -c two.gz > three.gz

$> ls -l
-rw-r--r--  1 uname  grp  1246 Mar  9 00:44 one.gz
-rw-r--r--  1 uname  grp  1306 Mar  9 00:44 three.gz
-rw-r--r--  1 uname  grp  1276 Mar  9 00:44 two.gz

这是一个很好的资源,解释了I/O重定向:http://www.codecoffee.com/tipsforlinux/articles2/042.html


我遇到的问题是mysqldump和gzip命令生效了。在第一个重定向到目录“backup”的时候,会创建一个0字节的文件。在第二个重定向到目录“backup2”且没有重新压缩的情况下,会创建我想要的文件。我想知道为什么会出现这种情况。 - user3397547
1
输出并没有被管道传输到gzip,而是被重定向了。它会一直重定向直到最后一部分,这时gzip会接手并对其进行压缩。 - m79lkm
1
Bash识别到重定向并首先尝试打开文件。文件被打开(创建),然后bash确定如何重定向数据。如果打开文件时出现错误,则命令失败并将错误写入stderr。如果输出再次被重定向,则第一个命令的stdin被发送到下一行中的文件。如果文件打开并且没有其他重定向,则数据将写入该文件。 - m79lkm
1
谢谢您解释bash重定向stdin输出到行尾,然后gzip在结尾处压缩文件。我想我的初始代码中有"> /dev/null 2>&1",导致mysqldump文件被发送到/dev/null并被丢弃。现在我的代码已经按照预期工作了。 - user3397547
1
小提示:不要在命令中添加密码。这将会被记录在历史记录中并且可以被检索到。(对于cron来说是可以的) - tibi
显示剩余2条评论

40

如果你需要在Centos7中将日期时间添加到备份文件名中,请使用以下命令:

/usr/bin/mysqldump -u USER -pPASSWD DBNAME | gzip > ~/backups/db.$(date +%F.%H%M%S).sql.gz

这将创建文件:db.2017-11-17.231537.sql.gz


19
除了m79lkm的解决方案,我对这个话题有一点建议:
选项1:
不要直接将结果通过管道传输到gzip,而是先将其转储为.sql文件,然后再进行gzip压缩。 所以,如果你有充足的磁盘空间,可以选择使用"&& gzip"而不是"| gzip"。
根据你的系统,转储本身可以快上两倍,但你需要更多的可用磁盘空间。你的表将被锁定的时间更短,因此应用程序的停机时间/响应速度较慢会减少。最终结果将完全相同。
所以非常重要的是首先检查可用的磁盘空间,使用"df -h"命令。
然后估计你的数据库转储大小,看看是否适合可用空间。
# edit this code to only get the size of what you would like to dump

SELECT Data_BB / POWER(1024,2) Data_MB, Data_BB / POWER(1024,3) Data_GB
FROM (SELECT SUM(data_length) Data_BB FROM 
information_schema.tables WHERE table_schema NOT IN ('information_schema','performance_schema','mysql')) A;

(来源:dba.stackexchange.com/a/37168
然后按照以下方式执行您的转储操作:
mysqldump -u user-p [database_name] > dumpfilename.sql && gzip dumpfilename.sql

选项2:

另一个提示是使用选项--single-transaction。它可以防止表被锁定,但仍然可以得到一个可靠的备份!在这里查看文档。而且,由于这个选项对于大多数查询来说并不会锁定你的表,你实际上可以直接将转储数据 | 压缩成gzip格式...(以防你没有足够的磁盘空间)

mysqldump --single-transaction -u user -p [database_name] | gzip > dumpfilename.sql.gz

1
好的建议。我认为两种方法的相对性能取决于系统规格。例如,如果您在具有快速CPU和大量快速内存但慢存储器的计算机上获得非常不同的结果,与在具有较少计算和内存但快速SSD的计算机上获得的结果不同。我建议对比测试这两种方法,以确定哪种更快/更优。同样适用于另一方向。还取决于机器是否具有用于DB表数据和文件系统(这是常见情况)的不同存储设备。像往常一样,你的经验可能会有所不同。 - Gruff

12
您可以使用tee命令重定向输出:
/usr/bin/mysqldump -u user -pupasswd my-database | \
tee >(gzip -9 -c > /home/user/backup/mydatabase-backup-`date +\%m\%d_\%Y`.sql.gz)  | \
gzip> /home/user/backup2/mydatabase-backup-`date +\%m\%d_\%Y`.sql.gz 2>&1

请查看此处的文档。


我的问题是第一个重定向导致一个0字节的文件,而第二个重定向导致完整的文件。 - user3397547
2
抱歉 - 我回答了你原来的问题。我会把这个留在这里 - 希望这个小片段对某人有用。 - m79lkm
1
确实是的 :) - Paolo Stefan

1

个人而言,我在根目录下创建了一个名为file.sh (权限755)的文件,通过crontab定时执行。

crontab代码:

10 2 * * * root /root/backupautomatique.sh

File.sh代码:

rm -f /home/mordb-148-251-89-66.sql.gz #(用于删除旧文件)

mysqldump mor | gzip > /home/mordb-148-251-89-66.sql.gz (完成数据备份)

scp -P2222 /home/mordb-148-251-89-66.sql.gz root@otherip:/home/mordbexternes/mordb-148-251-89-66.sql.gz

(将备份文件发送到其他地方,以防发送服务器崩溃或者太老,就像我一样;-))


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接