【问题标题】:Can a COMMIT statement (in SQL) ever fail? How?COMMIT 语句(在 SQL 中)会失败吗?如何?
【发布时间】:2011-04-26 23:42:52
【问题描述】:

在处理数据库事务时,假设事务中的所有语句都已毫无问题地执行,有哪些可能的条件(如果有)会导致事务中的最终 COMMIT 语句失败?


例如...假设您有一些 two-phasethree-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 而异?

【问题讨论】:

  • 如果这是家庭作业,请标记它。
  • @Bob Jarvis:哇。谢谢你让我感觉年轻了很多!
  • 家庭作业不是年龄的函数。 :-)
  • 这是哪个品牌的数据库?

标签: sql transactions


【解决方案1】:

COMMIT 可能会失败。您可能有足够的资源来记录您希望进行的所有更改,但缺乏实际实施更改的资源。

这还没有考虑它可能失败的其他原因:

  1. 更改本身可能不适合数据库的约束。

  2. 断电会导致事情无法完成。

  3. 请求的选择并发级别可能不允许更新(例如,游标更新已修改的表)。

  4. 提交可能会超时,或者由于饥饿问题而处于超时状态。

  5. 客户端和数据库之间的网络连接可能会丢失。

还有其他所有我想不到的“简单”原因。

【讨论】:

    【解决方案2】:

    某些数据库引擎可以将 UNIQUE 索引约束检查推迟到 COMMIT。显然,如果约束在提交时不成立,那么它将失败。

    【讨论】:

    • 真的吗?这就是我害怕的。你知道有什么引擎可以做到这一点吗?
    • 这是 PostgreSQL 9.0 中的一个新特性。 wiki.postgresql.org/wiki/…
    • Oracle 可以推迟 FK 约束检查,infolab.stanford.edu/~ullman/fcdb/oracle/or-triggers.html
    • @IgnacioVazquez-Abrams 如果它确实失败,那么交易的状态是什么?我们是否必须在那个时候发出回滚,或者我们已经被排除在事务之外了吗?
    • @ogc-nick:我不知道。检查文档。
    【解决方案3】:

    当然。

    在多用户环境中,COMMIT 可能会因为其他用户的更改而失败(例如,您的 COMMIT 在应用于当前数据库时会违反引用约束...)。

    托马斯

    【讨论】:

      【解决方案4】:

      当然,可能存在许多问题。提交行为本身必须做出一些最终的、永久的条目来指示事务已提交。如果输入失败,则事务无法提交。

      正如 Ignacio 所说,可以进行延迟约束检查(这可以是任何形式的约束,而不仅仅是唯一约束,具体取决于 DBMS 引擎)。

      SQL Server 特定:刷新 FILESTREAM 数据可以推迟到提交时间。那可能会失败。

      【讨论】:

        【解决方案5】:

        一个非常简单但经常被忽视的问题:硬件故障。如果底层服务器死机,提交可能会失败。这可能与磁盘、cpu、内存甚至网络相关。

        如果交易从未获得主人的批准(出于多种原因),则交易可能会失败。

        【讨论】:

          【解决方案6】:

          如果您使用的是两阶段提交,那么不会。所有可能出错的事情都在准备阶段完成。

          在提交期间仍可能出现网络中断、断电、宇宙射线等,但即便如此,事务仍将被写入永久存储,如果已触发提交,恢复过程应将其完成.

          希望。

          【讨论】:

          • 两阶段提交可能会失败。例如。当在事务中注册了多个资源并且在第二阶段中,其中一些资源的连接丢失(例如,该资源选择了最糟糕的崩溃时刻)。
          • @Richard 因此,“提交期间仍可能出现网络中断、电力不足、宇宙射线等”位。我相信我在写这篇文章时的想法是,即使该位在某种意义上失败了,事务也已写入磁盘,因此可以恢复它们,并且有效地,它们已经成功。如果我再次回答这个问题,我不确定我会不会这样说!
          【解决方案7】:

          无论系统设计得多么出色,提交都有可能陷入无法知道它是否成功的情况。在某些情况下,这可能无关紧要(例如,如果保存数据库的硬盘变成一堆渣,在此之前可能无法判断提交是否成功,但这并不重要);然而,在其他情况下,这可能是一个问题。特别是对于分布式数据库系统,如果在提交期间恰好发生连接失败,双方将无法确定对方是期待提交还是回滚。

          【讨论】:

            【解决方案8】:

            对于 MySQL 或 MariaDB,当与 Galera 集群一起使用时,COMMIT 是在检查集群中的其他节点时。所以,是的,COMMIT 可以发现重要的错误,您必须检查这些错误。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-06-12
              • 2017-03-23
              • 1970-01-01
              • 1970-01-01
              • 2012-07-02
              相关资源
              最近更新 更多