6

我是 MySQL 新手,我正在寻找使用mysqldump. 此页面建议使用此命令行:

mysqldump --single-transaction --flush-logs --master-data=2
          --all-databases > backup_sunday_1_PM.sql

但是...如果您仔细阅读文档,您会发现

--single-transaction转储过程中,为确保转储文件有效(正确的表内容和二进制日志位置),其他连接不应使用以下语句:ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE. 一致性读取与这些语句并不隔离,因此在要转储的表上使用它们可能会导致SELECT执行者mysqldump检索表内容获取不正确的内容或失败。

那么,有什么方法可以防止这种可能的转储损坏情况?即可以暂时阻止这些语句的命令。

PS:关于这个主题的 MySQL 错误条目http://bugs.mysql.com/bug.php?id=27850

4

4 回答 4

9

打开mysql命令窗口并发出以下命令:

mysql> FLUSH TABLES WITH READ LOCK;

这将锁定此 MySQL 实例上所有数据库中的所有表,直到您发出(或终止持有这些读锁的客户端连接)。UNLOCK TABLES

要确认这一点,您可以打开另一个命令窗口并尝试执行ALTERDROP或。这些命令挂起,等待读取锁被释放。按 Ctrl-C 终止等待。RENAMETRUNCATE

但是,虽然表具有读锁,但您仍然可以执行mysqldump备份。

FLUSH TABLES WITH READ LOCK命令可能与使用 的--lock-all-tables选项相同mysqldump。这并不完全清楚,但这个文档似乎支持它:

UNLOCK TABLES 的另一个用途是释放使用 FLUSH TABLES WITH READ LOCK 获得的全局读锁。

两者都FLUSH TABLES WITH READ LOCK使用--lock-all-tables“全局读锁”这个短语,所以我认为它们很可能会做同样的事情。因此,您应该能够使用该选项来mysqldump防止并发 ALTER、DROP、RENAME 和 TRUNCATE。


关于。您的评论:以下来自您链接到的 MySQL 错误日志中的 Guilhem Bichot:

你好。--lock-all-tables 调用 FLUSH TABLES WITH READ LOCK。因此,预计会阻止 ALTER、DROP、RENAME 或 TRUNCATE(除非有错误或我错了)。但是, --lock-all-tables --single-transaction 不能工作(mysqldump 会抛出错误消息):因为 lock-all-tables 在备份期间锁定服务器的所有表以防止写入,而单事务是旨在让写入发生在备份期间(通过在事务中使用一致读取 SELECT),它们本质上是不兼容的。

由此看来,您在备份期间无法获得并发访问,并同时阻止 ALTER、DROP、RENAME 和 TRUNCATE。

于 2009-01-23T21:30:37.717 回答
2

我认为阅读文档的那部分内容是一样的,但我发现了更多信息:

4.5.4. mysqldump — 数据库备份程序 http://dev.mysql.com/doc/en/mysqldump.html

对于 InnoDB 表,mysqldump 提供了一种进行在线备份的方法:

shell> mysqldump --all-databases --single-transaction > all_databases.sql

此备份在转储开始时获取所有表的全局读锁(使用 FLUSH TABLES WITH READ LOCK)。一旦获得了这个锁,就会读取二进制日志坐标并释放锁。如果在发出 FLUSH 语句时正在运行长更新语句,MySQL 服务器可能会停止,直到这些语句完成。之后,转储变为无锁并且不会干扰对表的读取和写入。如果 MySQL 服务器接收到的更新语句很短(就执行时间而言),那么即使有很多更新,初始锁定周期也不应该是明显的。

--opt--single-transaction选项有冲突:

- 选择

此选项是简写。与指定 --add-drop-table --add-locks --create-options --disable-keys --extended-insert --lock-tables --quick --set-charset 相同。它应该给你一个快速的转储操作并生成一个可以快速重新加载到 MySQL 服务器的转储文件。

--opt 选项默认启用。使用 --skip-opt 禁用它。

如果我正确理解您的问题,您希望将实际数据和 DDL(数据定义语言)放在一起,因为如果您只想要 DDL,您将使用--no-data. 有关这方面的更多信息,请访问:

http://dev.mysql.com/doc/workbench/en/wb-reverse-engineer-create-script.html

如果您希望创建数据库及其所有对象,请使用 --databases 选项和 mysqldump。如果脚本文件中没有 CREATE DATABASE db_name 语句,则必须将数据库对象导入现有模式,或者,如果没有模式,则创建新的未命名模式。

正如Michael Kofler 的 The Definitive Guide to MySQL 5所建议的那样,我建议以下选项:

--skip-opt
--single-transaction
--add-drop-table
--create-options
--quick
--extended-insert
--set-charset
--disable-keys

此外,--order-by-primary 如果您正在使用该--databases选项,则还应该使用该选项,--add-drop-database尤其是与此答案结合使用时。如果您要备份连接在不同网络上的数据库,则可能需要使用该--compress选项。

因此 mysqldump 命令(不使用--compress--databases--add-drop-database选项)将是:

mysqldump --skip-opt --order-by-primary --single-transaction --add-drop-table --create-options --quick --extended-insert --set-charset -h db_host -u username --password="myPassword" db_name | mysql --host=other_host db_name

我删除了--disable-keys书中给出的参考,因为据我了解,它对 InnoDB 无效。MySql 手册指出:

对于每个表,用 /*!40000 ALTER TABLE tbl_name DISABLE KEYS /;包围 INSERT 语句 和 / !40000 ALTER TABLE tbl_name ENABLE KEYS */; 陈述。这使得加载转储文件更快,因为索引是在插入所有行之后创建的。此选项仅对 MyISAM 表的非唯一索引有效。

我还发现了这个错误报告http://bugs.mysql.com/bug.php?id=64309,它在底部有来自Paul DuBois 的评论,他还写了几本书,除了这个特定问题我没有参考在该错误报告中找到的那些评论。

现在要创建“终极备份”,我建议考虑一下这个 shell 脚本的内容

  1. https://github.com/red-ant/mysql-svn-backup/blob/master/mysql-svn.sh
于 2014-02-19T03:39:57.487 回答
1

如果不锁定表,您将无法获得一致的转储。我只是在一天中没有注意到转储所需的 2 分钟的时间里做我的。

一种解决方案是进行复制,然后备份从属服务器而不是主服务器。如果从服务器在备份期间错过了写入,它将稍后赶上。这也将为您提供一个实时备份服务器,以防主服务器发生故障。这很好。

于 2013-05-12T14:48:39.483 回答
0

嗨,任何答案都晚了,但解决方案通过 BACKUP STAGE 到达 MariaDB,开源时间是相对主义的 :)

于 2022-02-18T13:57:53.767 回答