使用可串行化的转储比 MySQL 中的`--single-transaction`(可重复读取)更一致

问题描述 投票:0回答:1

我可以使用

--single-transaction
将所有数据库转储到 backup.sql,如下所示:

mysqldump -u john -p -A --single-transaction > backup.sql

实际上根据下面的文档

--single-transaction
使用REPEATABLE READ,它的一致性不如SERIALIZABLE,因为
REPEATABLE READ
无法防止丢失更新写入倾斜,而SERIALIZABLE可以:

此选项将事务隔离模式设置为

REPEATABLE READ
,并在转储数据之前向服务器发送
START TRANSACTION
SQL 语句。

那么现在有什么解决方案可以用

backup.sql
将所有数据库转储到
SERIALIZABLE
吗?

mysqldump -u john -p -A ????? > backup.sql
mysql database transactions serializable repeatable-read
1个回答
0
投票

Mysqldump 没有使用 SERIALIZABLE 事务隔离级别的选项。但你不需要它,这样做也不是一个好主意。

当两个会话在各自的更新时间安排上出现问题时,就会出现您提到的异常情况,即两个会话都在执行更新。

Mysqldump 只读取数据,不更新数据。因此,您无需担心更新丢失或写入偏差。

这不是一个好主意的原因是,MySQL 中的 SERIALIZABLE 的实现方式就像您将所有查询运行为“锁定读取”(例如 SELECT ... FOR SHARE)。然后,Mysqldump 将连续查询每个表,并在到达每个表时获取锁。在这些情况下,执行自己的更新的其他并发会话可能会被 mysqldump 持有的锁阻塞,并且它们将等待。如果他们已经在 mysqldump 尚未读取的任何表上持有锁,那么 mysqldump 将被他们的锁阻塞。这会导致僵局。

防止死锁的方法是使用

悲观锁定

,换句话说,在任何读取开始之前,将所有资源作为一个原子操作获取锁定。 Mysqldump 确实有一个选项:

--lock-all-tables

。这当然会阻止所有其他会话在 mysqldump 运行时运行查询,但它可以防止死锁。

© www.soinside.com 2019 - 2024. All rights reserved.