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服务器是否有办法从“未完成”的回滚中恢复?
答案 0 :(得分:5)
这是否意味着数据库仍然存在损坏
请注意,代码段中的任何内容都不会导致数据库 损坏。它同时跟踪数据的原始状态和您在交易中所做的更改。
rollback()
引发的异常是为了客户的利益,而不是服务器。尝试回滚时网络中断会触发异常,以便客户端可以尝试处理它,并且因为正常进行没有用处。从服务器的角度来看,回滚是丢弃事务内容的明确指令。如果rollback命令永远不会到达数据库,则数据库将暂停提交更改,直到它确定不再需要更改为止,此时将清除更改以清除服务器中的内存或磁盘空间。
如果您之前没有看过,那么您可能正在寻找ACID这个词;这描述了如何设计数据库和其他并发系统以减轻这类故障。符合ACID的数据库旨在保持一致,即使在提交或回滚中途发生物理故障 - 提交更改的最后一步(在DB内部)应该是原子的,以便成功或被丢弃。
作为一个切向示例,Mercurial在确保提交永远不会使the repo处于不一致状态时也有类似的担忧。当用户提交更改时,需要将更新写入多个文件,并且这些写入中的任何一个都可能失败。因此,它会谨慎地执行这些写操作,以确保避免不一致。
如果Mercurial在revlog或manifest文件中遇到未知的变更集ID,则会忽略它;从而确保变更完全承诺或根本不变。
已经有一段时间了,因为我在Mercurial内部进行了探讨,我完全有可能将其中的一些弄糊涂,但要点是正确的。