使用数据库事务时,可能导致事务中最终COMMIT
语句失败的可能条件(如果有),假设事务中的所有语句都已执行而没有问题?
例如......假设您有一些two-phase或three-phase commit protocol,其中您执行了大量语句,然后等待一些主进程告诉您何时可以最终提交事务:
-- <initial handshaking stuff>
START TRANSACTION;
-- <Execute a bunch of SQL statements>
-- <Inform master of readiness to commit>
-- <Time passes... background transactions happening while we wait>
-- <Receive approval to commit from master (finally!)>
COMMIT;
如果您的代码到达最后的COMMIT语句并将其发送到您的DBMS,您是否会在该语句中遇到错误(唯一性问题,数据库已满等)?什么错误?为什么?它们是如何出现的?它会根据您运行的DBMS而有所不同吗?
答案 0 :(得分:16)
COMMIT可能会失败。您可能拥有足够的资源来记录您希望进行的所有更改,但缺乏实际实施更改的资源。
并没有考虑其可能失败的其他原因:
更改本身可能不符合数据库的约束。
断电会使事情无法完成。
请求的选择并发级别可能会禁止更新(例如,游标更新已修改的表)。
提交可能会超时或处于由于饥饿问题而超时的连接上。
客户端和数据库之间的网络连接可能会丢失。
所有其他“简单”的理由并不是我的首要任务。
答案 1 :(得分:9)
有些数据库引擎可能会将UNIQUE索引约束检查推迟到COMMIT。显然,如果约束在提交时不成立,那么它将失败。
答案 2 :(得分:5)
不确定
在多用户环境中,由于其他用户的更改,COMMIT可能会失败(例如,当应用于当前数据库时,COMMIT会违反参照约束...)。
托马斯
答案 3 :(得分:4)
当然,可能存在许多问题。提交行为本身必须做出最终的永久性条目,以表明交易已经发生。如果使该条目失败,则该事务无法提交。
正如Ignacio所说,可以进行延迟约束检查(这可以是任何形式的约束,而不仅仅是唯一约束,具体取决于DBMS引擎)。
SQL Server特定:刷新FILESTREAM数据可以延迟到提交时间。那可能会失败。
答案 4 :(得分:4)
一个非常简单且经常被忽视的项目:硬件故障。如果底层服务器死亡,提交可能会失败。这可能是磁盘,CPU,内存,甚至是网络相关。
如果交易从未得到主人的批准(由于多种原因),交易可能会失败。
答案 5 :(得分:4)
如果你正在使用两阶段提交,那么没有。可能出错的一切都是在准备阶段完成的。
在提交过程中仍然可能出现网络中断,电量减少,宇宙射线等,但即便如此,事务也会被写入永久存储,如果已经触发了提交,则恢复过程应该通过
希望。
答案 6 :(得分:1)
无论系统设计得多么奇妙,提交都有可能进入无法知道系统是否成功的情况。在某些情况下,它可能并不重要(例如,如果持有数据库的硬盘驱动器变成一堆炉渣,则可能无法在发生之前判断提交是否成功,但这并不重要);然而,在其他情况下,这可能是一个问题。特别是对于分布式数据库系统,如果在提交期间恰当的时间发生连接失败,双方都可以确定另一方是否期望提交或回滚。
答案 7 :(得分:0)
对于 MySQL 或 MariaDB,当与 Galera 集群一起使用时,COMMIT
是检查集群中其他节点的时间。因此,是的,COMMIT
可以发现重要错误,您必须检查这些错误。