如何“安全地”恢复MySQL数据库

时间:2017-12-13 16:08:12

标签: mysql mysql-backup

你应该如何“安全地”恢复(并备份)MySQL数据库? “安全”是指:恢复应该创建/覆盖所需的数据库,但不要冒险改变数据库之外的任何内容

我已阅读https://dev.mysql.com/doc/refman/5.7/en/backup-types.html

我有外部用户。他们&我可能想要交换备份以进行恢复。我们拥有商业MySQL企业备份,正在寻找第三方商业产品。

在Microsoft SQL Server中,有BACKUPRESTORE命令。 BACKUP创建一个只包含所需数据库的文件;它的行和它的所有架构/结构都包含在内。 RESTORE接受此类文件,并创建或覆盖其结构。用户可以还原到同名数据库,也可以指定其他数据库名称。这种行为正是我所寻找的。

在MySQL中,我遇到了三种可能性:

  1. 大多数人似乎使用mysqldump来创建“转储文件”,并使用mysql来读取它。转储文件包含任意MySQL语句的列表,它们只是由mysql执行。这是非常不可接受的:文件可能包含任何 SQL语句。 (限制恢复用户的访问权限以确保它不能做任何“淘气”是不可接受的。)还有一个问题是用户可能已经使用“Include CREATE Schema”选项(MySQL Workbench)创建了转储文件,对原始数据库名称进行硬编码以进行重新创建。这种“转储”方法对我来说完全不合适,我发现任何人都会在生产环境中使用它会令人惊讶。

  2. 我遇到了MySQL的SELECT ... INTO OUTFILELOAD DATA INFILE语句。至少它们不包含要执行的SQL代码。但是,它们看起来像很多工作,时间处理表而不是整个数据库,并且不处理表的结构,你必须知道自己要进行恢复。有一个mysqlimport帮助程序命令行实用程序,但我没有看到导出端的任何内容,我没有看到它用于还原完整的数据库。

  3. 最后一个是使用MySQL所谓的“物理(原始)”而不是“逻辑”备份。这适用于数据库目录和文件本身。它相当于SQL Server的detach / attach方法用于备份/恢复。但是,根据https://dev.mysql.com/doc/refman/5.7/en/backup-types.html,它有各种各样的警告,例如“备份只能移植到具有相同或类似硬件特征的其他机器上。” (我不知道,例如某些用户是Windows与Windows,我不知道他们的架构)和“备份可以在MySQL服务器未运行时执行。如果服务器正在运行,则需要执行适当的锁定以便服务器在备份期间不会更改数据库内容。“ (更不用说恢复了。)

  4. 如上所述,对于MySQL备份/恢复,我能满足(我认为是什么)我的适度要求吗?我是否真的是唯一一个将上述3作为唯一但不可接受的可能解决方案的人?

3 个答案:

答案 0 :(得分:1)

如果您不打算使用第三方工具(例如innobackupex),那么您只能使用mysqldump,它位于mysql包中。
我无法理解为什么你不能接受,为什么你不喜欢那些转储中的sql命令。将单个数据库还原到已包含其他数据库的服务器时,最佳做法是拥有一个单独的用户,只有权限才能写入已还原的数据库。然后,即使用户执行还原,也会更改sql命令并尝试写入另一个db,它们将无法执行。
在进行原始备份(数据库文件的物理副本)时,需要关闭所有实例,mysql服务器不运行。类似的硬件意味着您需要与源服务器具有相同的目录(除非您在启动服务器之前更改my.cnf,并将所有文件放到正确的目录中)。
进入mysql时,尽量不要将它与sql server进行比较 - 它是完全不同的方法和理念。
但如果你说服自己无论如何使用第三方工具 - 我推荐Percona的innobackex,这是免费的。

答案 1 :(得分:1)

1 - mysqldump - 我经常使用这个,通常是在我自己处理所有细节的环境中。我有一个配置,我使用它来发送开发数据库的副本 - 完全转储/恢复 - 给其他开发人员。它可能是最快的解决方案,具有一些合理的配置选项(例如,包括/排除特定表)并生成非常实用的SQL代码(例如,每个INSERT批处理足够小以避免锁定/速度问题)。对于“替换整个数据库”或“替换特定数据库中的密钥表”解决方案,它可以很好地工作。我并不太关心“任意SQL命令”问题 - 如果这是一个问题,那么用户可能会遇到其他问题“尝试做自己的事情”。

2 - SELECT ... INTO OUTFILELOAD DATA INFILE - 这些问题是如果你有任何非常大的表,那么LOAD DATA INFILE语句可能会导致问题,因为它试图加载所有内容一旦。您还必须添加代码以创建(如果需要)或在LOAD DATA之前清空表。

3 - 物理(原始)文件传输。这个可以工作,但在有限的情况下。我遇到了一个带有数千兆字节数据库的情况,并决定压缩原始文件,将它们移动到新机器,解压缩并告诉MySQL“一切都已存在”。它大多运作良好。但由于存在许多可能的问题,我不建议将其用于任何无人值守/最终用户进程。

我建议做什么

1 - mysqldump - 有其局限性和风险,设置一个脚本来调用mysqldump并压缩文件(我很确定mysqldump中有选项可以自动进行压缩),包含日期文件名,以便在发送文件时减少混淆,并为用户创建一个简单的脚本来加载文件。

2 - 编写自己的程序。我这样做了几次。这是最初的工作,但允许您控制进程的每个方面,并传输仅包含数据的文件,而不需要任何实际的SQL代码。您可以控制特定的数据库,表等。一个问题是,如果您对表结构,索引等进行任何更改,您将需要确保以某种方式将信息传输到接收问题,以便它可以更改结构根据需要 - 这不是mysqldump的问题,因为它通常会替换表,创建新结构,索引等。这可以用任何可以连接到MySQL的语言编写 - 它不一定是与您的申请语言相同。

答案 2 :(得分:1)

补充mysqlimport的导出工具是mysqldump --tab。这会输出像SELECT...INTO OUTFILE这样的CSV文件。它还以更小的.sql文件输出表结构。因此每个表有两个文件。

从.sql文件重新创建表后,可以使用mysqlimport导入所有数据文件。您甚至可以使用mysqlimport --use-threads选项使其并行加载多个数据文件。

通过这种方式,您可以更好地控制将数据加载到哪个架构中,并且运行速度比加载大型SQL转储要快得多。

相关问题