代码之家  ›  专栏  ›  技术社区  ›  fletcher

数据库事务-它们是如何工作的?

  •  29
  • fletcher  · 技术社区  · 14 年前

    我正试图了解更多关于数据库事务的信息,我发现了编写事务的经验法则,并考虑了几个问题。

    经验法则:

    交易必须:

    1. 原子-它是一个工作单元,不依赖于前一个和 后续交易。
    2. 一致性-数据已提交或回滚,否 在两种情况之间 更新了一些东西。
    3. 隔离-没有事务看到当前的中间结果 交易。
    4. 持久性-如果数据已提交,即使 系统随即崩溃。

    我想知道他们是如何在幕后工作的,所以我可以更好地理解在写这样的交易时需要考虑的因素。我想具体的细节在可用的数据库实现之间会有所不同,但是某些规则会一直存在。

    1. 在仍然支持原子规则的情况下,数据库如何处理并发事务?
      • 是否有按顺序处理的事务队列?
      • 如何处理阻碍所有其他交易的冗长交易?
    2. 是否在内存中更新了表,因此如果在提交之前发生崩溃,则不会更改数据库?
      • 或者是否有一些中间表被更新以在这种崩溃中幸存?
    3. 当事务正在进行时,是否阻止对受影响表的所有读写访问?
      • 或者数据库允许写操作,但事务在提交时会覆盖所有更改?
    6 回复  |  直到 6 年前
        1
  •  14
  •   fredley    14 年前
    1. 有许多不同的方法,包括事务排队、乐观并发控制等。这实际上是一个非常复杂的问题,有很多书都写过:

      http://www.amazon.co.uk/Databases-Transaction-Processing-Application-Oriented-Approach/dp/0201708728/ref=sr_1_3?ie=UTF8&s=books&qid=1281609705&sr=8-3

    2. 这取决于数据库中的日志记录级别。如果保留了严格的提前写入日志,那么在系统崩溃的情况下,数据库可以恢复到一致的状态。

    3. 这取决于并发的类型。乐观并发不涉及锁,但如果事务完成后数据库的状态发生了变化,则放弃并重新启动数据库。这可以加速发生碰撞的DBS。还有不同级别的锁定:行、表,甚至整个数据库。

    这些问题非常复杂,我建议您购买一本书,或者参加并发系统系列讲座,如果您想完全回答这些问题的话:—)

        2
  •  11
  •   Nanne    12 年前

    对你的定义有几点吹毛求疵:

    原子-它是一个工作单元,不依赖于之前和之后的事务。

    原子性的更正确定义不会提及任何“先前或之后”的事务。原子性是一个事务本身所具有的属性,也就是说,在最后的倒计时中,它的所有操作要么都保持不变,要么根本不存在。换句话说,不应允许“只有一半的交易”持续下去。

    然而,这个概念被嵌套事务、保存点等概念模糊了,并且用户可以请求显式回滚到所取的保存点。在某种意义上,它们确实允许“只有事务的一半操作”持续存在,所有这些都是在显式用户的请求下进行的。

    一致性-数据要么是提交的,要么是回滚的,在某些内容被更新和没有更新的情况下是不一致的。

    这种解释是完全错误的。一致性意味着事务处理器(在本例中是DBMS引擎)不能使系统(数据库)处于违反其(事务处理器)所知道的任何声明约束的状态。例如,参见“数据库系统简介”,第16章。

    隔离-没有事务看到当前事务的中间结果。

    吹毛求疵:无交易 除了电流 允许查看中间状态(状态,不是真正的结果)。还要注意,事务处理引擎的“隔离级别”通常定义了I属性可以被违反的程度!

    持久性-如果提交了数据,即使系统在之后崩溃,这些值也会保持不变。

    但这种属性也被嵌套事务的可能性模糊了一点。即使内部事务已提交并完成,包含该事务的事务仍然可以通过自身完全回滚来撤消该提交。

        3
  •  6
  •   om-nom-nom Dennis Williamson    11 年前

    实际的细节可能在某种程度上取决于它是哪个数据库服务器,但本文可能会让您感兴趣: Transaction Processing Cheat Sheet

        4
  •  3
  •   Community CDub    7 年前

    在执行方面,有不平衡的努力来保证 ACID 性质。我可以用我的简化思想来总结:

    • tomicity最终依赖于锁定或其他原子操作来交换事务中修改的数据(创建于 在共享视图中使用原始数据。

      在仍然支持原子规则的情况下,数据库如何处理并发事务?

      溶剂化。

    • C 和谐依赖于更基本的 断层和 隔离属性和扩展到应用层,而不是本质上属于数据库服务。

      确保规则(何时 断层和 通过在修改后的数据上执行它们,可以很容易地得到安慰。

      这可能引发哲学争论。但在我看来,在其非常重要的情况下,在相关数据最终提交之前,可以在应用程序逻辑中或在数据库层中的特定于应用程序的过程中实现对所有条件的验证,而这并不能使它们成为特定于数据库的过程。数据库服务必须确保的最低限度是能够读取以前写入的数据而不会出错。

      是否在内存中更新了表,因此如果在提交之前发生崩溃,则不会更改数据库?

      溶剂化。

      注意 C 内在一致性 纯粹是逻辑的、静态的,没有与数据传播相关的级别或等级。 CAP theorem .

    • 通过首先修改原始数据的副本(在提交对共享视图的更改之前),可以普遍实现隔离。

      当事务正在进行时,是否阻止对受影响表的所有读写访问?

      通常,如果在一个事务中只修改数据的副本,其他事务就不会看到这些更改。但是,隔离级别可能不同。

      这是唯一的 允许具有一定级别和度而不只是黑白的属性。

      最终, “慰藉”是其实施过程中最深刻的,也是所有人之间可能达成的权衡。 性质。和 going in details 关于这个属性是关于数据库服务保证的第一个最重要的主题(即使在 盖帽定理 在这种情况下,权衡又围绕着分布式数据上孤立视图的一致性发展)。

    • D 耐久性实际上是一种 SLA .

      什么样的耐久性(“写入可腐蚀磁盘”或“在钚驱动服务器的RAM中冗余分布”)通常在正常事务逻辑之外进行协商。

      实现也相当简单,归根结底就是只有在刷新所有可能的缓冲区之后才确认成功的事务。

    对性能至关重要的两个实施方面(即 不关心):

    • 冲突检测

      应该有一种方法(有效地)检测在另一个事务中同时进行的冲突更改。

      一个极端点是锁定所有不需要冲突检测(没有可能的并发性)的东西。

      另一个极端点是乐观并发(至少部分)。然后需要知道是否有并发的变更。这可以通过对数据库中的各个对象运行计数器(版本号)或校验和来实现。然后,这与 溶剂化。

    • 回滚过程

      这需要维护原始值及其修改副本(事务日志)的数据结构以撤消更改。同样,这与 实施安慰。

    一些附加的简短信息:

        5
  •  1
  •   beldaz Nicolas W.    14 年前

    一致性-数据要么已提交 或者向后滚,不在中间 更新了一些东西, 什么都没有。

    我不同意埃尔文·斯穆特关于“一致”意味着什么的观点——你的解释更接近于金钱。根据我的解释 Ramakrishnan and Gehrke A 一致状态 超出了系统的声明约束。

    如果通过借记一个账户和贷记另一个账户在两个账户之间转账,系统可能处于以下几种状态:

    1. 两个账户都持有初始余额;
    2. 从一个账户余额中扣除,但不计入其他账户余额;
    3. 金额从一个账户余额中增加,但不从另一个账户余额中扣除;
    4. 两个账户都持有最终余额。

    在这四种状态中,系统的完整性约束都可以保持。但是第二个和第三个不符合一个合理的制度观——金钱 应该在某个地方 . 所以这些状态是不一致的,而初始状态和最终状态是一致的。

    事务不会自动使系统保持一致-它们允许用户将它们写入一致。一个写得不好的交易可能有一个错误,忘记将第二个帐户记入贷方。事务将运行良好,完整性约束将保持不变。

    但是一个正确的书面程序将系统从一个一致的状态中取出,做出一些暂时不一致的更改(例如,货币不在任何一个帐户中),然后将系统恢复到一个一致的状态。通过在事务中放置这些步骤,可以保证系统达到最终一致状态(提交时)或返回到初始一致状态(如果系统回滚)。无论哪种方式,都会保持一致性。

        6
  •  0
  •   Erwin Smout    14 年前

    “关于嵌套交易的裁决是什么?”

    没有判决。存在嵌套事务。酸性物质存在。他们被迫共存。没有绝对的。当然不会酸。