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

SHH*_*SHH 9 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?
    }
}
Run Code Online (Sandbox Code Playgroud)

对于MySQL服务器(InnoDB Engine),如果事务的rollback()失败会发生什么?(即当rollback()正在运行时网络正常运行,等等...)

这是否意味着数据库仍然存在损坏,或者MySQL服务器是否有办法从"未完成"的回滚中恢复?

dim*_*414 8

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

请注意,在您的代码段没有点具有DB 成为损坏.它同时跟踪数据的原始状态和您在事务中所做的更改.

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

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


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

  1. 首先,将单个文件差异附加到repo中与变更集ID关联的关联revlog文件.
  2. 然后更新列出这些更改的清单,再次绑定到变更集ID.
  3. 只有上述所有操作都成功后,变更集ID本身才会记录在更改日志中(这是单个原子写入).如果此写入成功,则提交成功.

如果Mercurial在revlog或清单文件中遇到未知的变更集ID,则会忽略它; 从而确保变更完全承诺或根本不变.

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