我可以使用
--single-transaction将所有数据库转储到
backup.sql
,如下所示:
mysqldump -u john -p -A --single-transaction > backup.sql
实际上根据下面的文档,
--single-transaction
使用REPEATABLE READ,它的一致性不如SERIALIZABLE,因为REPEATABLE READ
无法防止丢失更新和写入倾斜,而SERIALIZABLE可以:
此选项将事务隔离模式设置为
,并在转储数据之前向服务器发送REPEATABLE READ
SQL 语句。START TRANSACTION
那么现在有什么解决方案可以用
backup.sql
将所有数据库转储到 SERIALIZABLE
吗?
mysqldump -u john -p -A ????? > backup.sql
Mysqldump 没有使用 SERIALIZABLE 事务隔离级别的选项。但你不需要它,这样做也不是一个好主意。
当两个会话在各自的更新时间安排上出现问题时,就会出现您提到的异常情况,即两个会话都在执行更新。
Mysqldump 只读取数据,不更新数据。因此,您无需担心更新丢失或写入偏差。
这不是一个好主意的原因是,MySQL 中的 SERIALIZABLE 的实现方式就像您将所有查询运行为“锁定读取”(例如 SELECT ... FOR SHARE
)。然后,Mysqldump 将连续查询每个表,并在到达每个表时获取锁。在这些情况下,执行自己的更新的其他并发会话可能会被 mysqldump 持有的锁阻塞,并且它们将等待。如果他们已经在 mysqldump 尚未读取的任何表上持有锁,那么 mysqldump 将被他们的锁阻塞。这会导致僵局。
,换句话说,在任何读取开始之前,将所有资源作为一个原子操作获取锁定。 Mysqldump 确实有一个选项:
。这当然会阻止所有其他会话在 mysqldump 运行时运行查询,但它可以防止死锁。