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

时间:2015-05-01 02:52:43

标签: java mysql transactions rollback

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 个答案:

答案 0 :(得分:5)

  

这是否意味着数据库仍然存在损坏

请注意,代码段中的任何内容都不会导致数据库 损坏。它同时跟踪数据的原始状态和您在交易中所做的更改。

rollback()引发的异常是为了客户的利益,而不是服务器。尝试回滚时网络中断会触发异常,以便客户端可以尝试处理它,并且因为正常进行没有用处。从服务器的角度来看,回滚是丢弃事务内容的明确指令。如果rollback命令永远不会到达数据库,则数据库将暂停提交更改,直到它确定不再需要更改为止,此时将清除更改以清除服务器中的内存或磁盘空间。

如果您之前没有看过,那么您可能正在寻找ACID这个词;这描述了如何设计数据库和其他并发系统以减轻这类故障。符合ACID的数据库旨在保持一致,即使在提交或回滚中途发生物理故障 - 提交更改的最后一步(在DB内部)应该是原子的,以便成功或被丢弃。

作为一个切向示例,Mercurial在确保提交永远不会使the repo处于不一致状态时也有类似的担忧。当用户提交更改时,需要将更新写入多个文件,并且这些写入中的任何一个都可能失败。因此,它会谨慎地执行这些写操作,以确保避免不一致。

  1. 首先,将单个文件差异附加到回购中与关联变更集ID关联的revlog文件中。
  2. 然后更新列出这些更改的清单,再次绑定到变更集ID。
  3. 只有上述所有操作都成功后,变更集ID本身才会记录在更改日志中(这是单个原子写入)。如果此写入成功,则提交已成功。
  4. 如果Mercurial在revlog或manifest文件中遇到未知的变更集ID,则会忽略它;从而确保变更完全承诺或根本不变。

    已经有一段时间了,因为我在Mercurial内部进行了探讨,我完全有可能将其中的一些弄糊涂,但要点是正确的。