【问题标题】:What is the best default transaction isolation level for an ERP, if any?什么是 ERP 的最佳默认事务隔离级别(如果有)?
【发布时间】:2010-09-26 17:29:19
【问题描述】:

简短背景:我们刚刚开始使用 Hibernate 将 ERP 系统迁移/重新实现到 Java,目标是使用该系统的并发用户数为 50-100 个用户。我们使用 MS SQL Server 作为数据库服务器,足以应付这种负载。

现在,旧系统根本不使用任何事务,而是依赖于关键部分(例如库存更改)设置手动锁定(使用标志)并释放它们。这类似于手动事务管理。但有时会出现数据不一致的问题。在新系统中,我们希望使用事务来消除这些问题。

现在的问题是:考虑到大约 85% 的 OLTP 和 15% 的 OLAP 的使用情况,对于 ERP 系统使用什么好的/合理的默认事务隔离级别?还是我应该始终根据每个任务决定使用哪个事务级别?

提醒一下,四个事务隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE

【问题讨论】:

    标签: sql database database-design transactions


    【解决方案1】:

    100 次中有 99 次,读取已提交是正确答案。这可确保您只看到其他会话已提交的更改(因此,假设您正确设计了事务,结果是一致的)。但它不会强加可重复读取或可序列化强加的锁定开销(尤其是在非 Oracle 数据库中)。

    在极少数情况下,您可能希望运行一个报告,在该报告中您愿意牺牲准确性以换取速度并设置读取未提交的隔离级别。这很少是一个好主意,但它有时是一种合理的解决方法来解决争用问题。

    当您的进程需要在整个运行期间查看一致的数据集时,偶尔会使用可序列化和可重复读取,而不管当时其他事务正在做什么。将月末对账流程设置为可序列化可能是合适的,例如,如果有很多过程代码,用户可能会在流程运行时进行更改,并且需要流程需要确保它始终看到数据在对帐开始时存在的状态。

    【讨论】:

    • 根据用户数量,我不建议在您的主 OLTP 系统上运行报告。有一个日志发送(或以其他方式复制)端服务器,用于报告数据的非规范化版本
    【解决方案2】:

    不要忘记 SNAPSHOT,它位于 SERIALIZABLE 的正下方。

    这取决于报告中数据准确的重要性。这真的是一个任务一个任务的事情。

    【讨论】:

      【解决方案3】:

      这在很大程度上取决于您如何设计应用程序,简单的答案就是在 READ_COMMITTED 处运行。

      您可以提出一个论点,即如果您在设计系统时考虑到它可以使用 READ_UNCOMMITTED 作为默认值,并且仅在需要时增加隔离级别。无论如何,您的绝大多数事务都会成功,因此读取未提交的数据不会有什么大不了的。

      隔离级别影响查询的方式取决于您的目标数据库。例如,Sybase 和 MSSQL 等数据库在运行 READ_COMMITTED 时必须锁定比 Oracle 等数据库更多的资源。

      【讨论】:

        【解决方案4】:

        对于 SQL Server(可能是大多数主要的 RDBMS),我会坚持使用默认值。对于 SQL Server,这是 READ COMMITTED。再多一点,您就会开始对数据库造成负担过重,再少一点,您就会遇到一致性问题。

        【讨论】:

        • SQL Server 的默认值可能是 READ COMMITTED,但我相信 ADO.net 的默认值是 SERIALIZABLE,在这种情况下,如果他使用 .net 则更重要。
        • @Robert 这不正确。默认值是 SQL Server 上的默认值。例如,当您更改 SqlTransaction 上的隔离级别时,它会在服务器上执行 SET TRANSACTION ISOLATION LEVEL XXXX。
        【解决方案5】:

        Read Uncommitted 绝对是大多数论坛中的弱者。但是,使用它的理由超出了经常被指出的“速度与准确性”的问题。

        假设你有:

        • 事务 T1:写入 B,读取 A,(更多工作),提交。
        • 事务 T2:写入 A,读取 B,(更多工作),提交。

        读取提交后,上述事务在提交之前不会释放。那么就可以遇到T1在等待T2释放A,而T2在等待T1释放B的情况。这里两个事务在锁中发生冲突。

        您可以重新编写这些程序来避免这种情况(例如:总是按字母顺序获取资源!)。尽管如此,由于并发用户过多且代码数以万计,这个问题可能变得非常可能而且非常难以诊断和解决。

        另一种方法是使用未提交的读取。然后你设计你的事务,假设可能有脏读。我个人认为这个问题比联锁的火车残骸更局部化和可治疗。

        脏读的问题可以被

        抢占
        • (1) 回滚:不要。这应该是硬件故障、网络故障或程序崩溃的最后一道防线。

        • (2) 使用应用程序锁创建锁定机制 在更高的抽象层次上,每个锁都更接近于 现实世界的资源或行动。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多