与 mysqldump 一致的 InnoDB 转储

Consistent InnoDB dumps with mysqldump

MySQL 文档建议在使用 mysqldump 转储 InnoDB 时使用 --single-transaction 来获取数据库的事务一致快照,同时对其他事务的阻塞最少。不幸的是,这只有在您能以某种方式阻止任何其他连接在转储期间执行模式更改时才有效:

https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html

While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents and binary log coordinates), no other connection should use the following statements: ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE. A consistent read is not isolated from those statements, so use of them on a table to be dumped can cause the SELECT that is performed by mysqldump to retrieve the table contents to obtain incorrect contents or fail.

确保转储期间不会发生模式更改的好方法是什么?我的用例是我使用 mysqldump 实用程序每小时定期 (cronjob) 备份我的数据库。

我认为也许使用 mysqldump 的默认值 --lock-tables 代替会给我事务一致性,但是:

The --single-transaction option and the --lock-tables option are mutually exclusive because LOCK TABLES causes any pending transactions to be committed implicitly.

这是不是说如果有人针对 InnoDB 运行 mysqldump --lock-tables 它实际上会导致另一个会话中正在进行的事务不再是事务性的?我希望不会——这看起来很疯狂。其他地方:

https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html#lock-tables-and-transactions

LOCK TABLES and UNLOCK TABLES interact with the use of transactions as follows:

LOCK TABLES is not transaction-safe and implicitly commits any active transaction before attempting to lock the tables.

这在单个数据库会话的上下文中是有意义的。如果您在事务中间执行此操作,那么它会首先隐式提交您的未结事务。目前尚不清楚它对其他会话上的交易做了什么(如果有的话)。我希望它不会做任何事情,或者更确切地说,对于其他会话上任何正在进行的交易,它会始终如一地排序。

我是不是读了太多 mysqldump 文档并使用 --lock-tables 实现了事务一致性?

mysqldump 文档是否简单地解释了将 --single-transaction 与 --lock-tables 一起执行是荒谬的,因为 --lock-tables 会立即隐式关闭单个事务?但除此之外,mysqldump --lock-tables 在事务上是一致的吗?

谢谢!

Lock tables 强制在同一会话中提交事务 它不会强制在其他会话中提交。

如果您对 mysqldump 使用这两个选项,则 mysqldump 客户端打开的会话将启动一个事务,然后在锁定 tables 发生时立即提交该事务。所以没有必要一起使用它们。

此外,不会提交任何其他客户端的事务,但它们会阻止 mysqldump 的 lock-tables 操作。任何查询(即使是只读的 SELECT)都将获得一个 元数据锁 ,并且 lock-tables 将等待该元数据锁被释放。所以 mysqldump 将尝试获取 table 锁,并且必须等待。

同时,任何在 mysqldump 开始等待后尝试开始新事务的客户端也会等待,就好像它们在 mysqldump 后面的队列中一样。这势必会停止您的申请进度。

这种类型的等待不同于 50 秒后超时的常规行锁。元数据锁定等待的默认超时为 1 年(请参阅 https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_lock_wait_timeout)。

这几乎排除了在生产站点上使用 mysqldump --lock-tables 的可能性,不是吗?仅当您不使用事务性 table 时才应使用它。我已经很多年没有使用 --lock-tables 选项了。

如果使用 --lock-tables,任何 DDL 语句都会被阻止,因为 DDL 语句也需要独占元数据锁。

我不知道有什么方法可以在使用 --single-transaction 时阻止 DDL 语句。你只需要在备份 运行.

时避免这样做

我还要评论说,每小时制作一个完整的 mysqldump 可能不是最好的备份策略。您应该考虑减少备份的频率,然后使用二进制日志来进行时间点恢复。参见 https://dev.mysql.com/doc/refman/8.0/en/point-in-time-recovery.html