当MySQL中事务的rollback()操作失败时会发生什么?

14
try
{
    Connection conn = ... MySQL connection ...;
    conn.setAutoCommit(false); // transaction starts
    .... do something ....
}
catch (MySQLException e)
{
    try {
        conn.rollback();
    }
    catch (Exception e)
    {
        // What happens now?
    }
}
对于MySQL服务器(InnoDB引擎),如果事务回滚(rollback())失败会发生什么?(例如,当回滚(rollback())正在执行时网络中断等情况)
这是否意味着数据库保持损坏状态,或者MySQL服务器有没有从“未完成”的回滚中恢复的方法?

1
如果网络出现故障,那么说明回滚请求没有到达 MySQL 服务器,对吧?然后发生的任何更改都将保留。我希望您阅读了文档“仅当禁用自动提交模式时才应使用此方法。” - kosa
1
如果这是一个事务,那么事务中的所有操作只有在执行 .commit() 后才会被提交。希望您正在使用 MySQL,如果可以的话,请切换到 PostgreSQL。 - fge
1
我对commit()不感兴趣。我很好奇当rollback()失败时会发生什么,以及它如何影响MySQL数据库的完整性(它是否仍然损坏?或者它是否有从不完整回滚中恢复的机制)。 - SHH
如果您的连接中断,数据库服务器将回滚您的事务。 - user253751
如果数据库在回滚事务时出现除网络问题以外的其他原因,该怎么办? - SHH
显示剩余3条评论
1个回答

10
请注意,在代码片段中,DB 从未被“损坏”。它同时跟踪数据的原始状态和您在事务中所做的更改。rollback()引发的异常是为了客户端而不是服务器。尝试回滚时的网络故障会触发异常,以便客户端可以尝试处理它,并且因为正常进行无用。从服务器的角度来看,回滚是一条明确的指令,要丢弃事务的内容。如果回滚命令从未到达数据库,则数据库将仅暂停提交更改,直到它决定不再需要为止,此时更改将被清除以清除服务器中的内存或磁盘空间。
如果你之前没有看过,那么你可能正在寻找ACID这个术语;它描述了数据库和其他并发系统必须设计来减轻这些故障的方式。符合ACID标准的数据库旨在保持一致性,即使在提交或回滚的中途出现物理故障 - 在DB内部提交更改的最后一步应该是原子的,因此它要么成功,要么被丢弃。
作为一个类似的例子,Mercurial 也有类似的担忧,确保提交不会使 仓库 处于不一致状态。当用户提交更改时,需要将更新写入多个文件,其中任何一个写操作都可能失败。因此,它按照仔细的顺序进行这些写操作,以确保避免不一致性。
  1. 首先,将单个文件差异附加到与更改集 ID 相关联的存储库中的其关联的 revlog 文件中。
  2. 然后,更新列出这些更改的清单,再次与更改集 ID 相关联。
  3. 只有在所有上述操作都成功完成后,才会记录更改集 ID 本身在更改日志中(这是单个原子写入)。如果此写入成功,则提交已成功。

如果 Mercurial 在 revlog 或清单文件中遇到未知的更改集 ID,则会忽略它;从而确保更改已完全提交或根本没有提交。

我已经有一段时间没深入研究 Mercurial 的内部了,我可能把一些东西搞混了,但主要思想是正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接