如何恢复 MySQL 数据库 "safely"

How to restore a MySQL database "safely"

您应该如何恢复(和备份)MySQL 数据库 "safely"? "safely" 我的意思是:恢复应该 create/overwrite 一个想要的数据库, 但不要冒险改变数据库之外的任何东西 .

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

我有外部用户。他们和我可能想交换备份以进行恢复。我们没有商业MySQL企业备份,并且没有寻找第三方商业产品。

在 Microsoft SQL 服务器中有 BACKUPRESTORE 命令。 BACKUP 创建一个只包含您想要的数据库的文件;它的行和所有 schema/structure 都包括在内。 RESTORE 接受这样的文件,并创建或覆盖其结构。用户可以恢复到同名数据库,或指定不同的数据库名称。这种行为正是我要找的。

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

  1. 大多数人似乎使用 mysqldump 创建一个 "dump file",然后 mysql 将其读回。转储文件包含任意 MySQL 语句,它们仅由 mysql 执行。这是完全无法接受的table:该文件可能包含any SQL 语句。 (限制恢复用户的访问权限以确保它不能做任何事情 "naughty" 是不可接受的 table。)还有一个问题是用户可能已经使用 [=64= 创建了转储文件] 选项 (MySQL Workbench),它对原始数据库名称进行硬编码以便重新创建。这种"dump"方法对我来说完全不合适table,我发现有人会在生产环境中使用它感到惊讶。

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

  3. 最后一个是使用 MySQL 提到的 "Physical (Raw)" 而不是 "Logical" 备份。这适用于数据库目录和文件本身。它等同于 SQL 服务器的 detach/attach 支持 up/restoring 的方法。但是,根据 https://dev.mysql.com/doc/refman/5.7/en/backup-types.html,它有各种警告,例如"Backups are portable only to other machines that have identical or similar hardware characteristics."(我不知道,例如一些用户是 Windows 与 Windows,我不知道他们的架构)和 "Backups can be performed while the MySQL server is not running. If the server is running, it is necessary to perform appropriate locking so that the server does not change database contents during the backup."(更不用说恢复了)。

那么,有什么能满足(我认为的)我对 MySQL backup/restore 的适度要求吗?我真的是唯一一个发现以上 3 种唯一但未接受table 可能解决方案的人吗?

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

1 - mysqldump - 我经常使用它,通常是在我自己处理所有细节的环境中。我确实有一个配置,我用它来发送开发数据库的副本 - 整个 dumped/restored - 给其他开发人员。它可能是最快的解决方案,有一些合理的配置选项(例如,include/exclude 特定的 tables)并生成非常实用的 SQL 代码(例如,每个 INSERT 批次足够小以避免locking/speed 个问题)。对于 "replace entire database" 或 "replace key tables in a specific database" 解决方案,它工作得很好。我不太关心 "arbitrary SQL commands" 问题 - 如果这是一个问题,那么您可能会遇到其他问题,因为用户试图 "do their own thing".

2 - SELECT ... INTO OUTFILELOAD DATA INFILE - 这些的问题是,如果你有任何非常大的 table,那么 LOAD DATA INFILE 语句可能会导致问题,因为它正在尝试一次加载所有内容。您还必须添加代码以在 LOAD DATA.

之前创建(如果需要)或清空 tables

3 - 物理(原始)文件传输。此 可以 工作,但在有限的情况下。我遇到过一个数 GB 数据库的情况,我决定压缩原始文件,将它们移动到新机器上,解压缩并告诉 MySQL "everything is already there"。它主要运作良好。但我不建议将它用于任何 unattended/end-user 过程,因为可能存在许多问题。

我推荐做什么

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

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

补充 mysqlimport 的导出工具是 mysqldump --tab。这会输出 CSV 文件,如 SELECT...INTO OUTFILE。它还在更小的 .sql 文件中输出 table 结构。所以每个 table.

有两个文件

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

通过这种方式,您可以更好地控制将数据加载到哪个模式,而且它应该 运行 比加载大型 SQL 转储快得多。