【问题标题】:NHibernate transaction and race conditionNHibernate 事务和竞争条件
【发布时间】:2008-09-23 08:08:22
【问题描述】:

我有一个 ASP.NET 应用程序,它使用 NHibernate 在用户操作时以事务方式更新一些表。涉及一个日期范围,因此只能在“预订”表中输入一个条目,以便指定排他日期。

我的问题是如何防止竞争条件,即两个用户操作几乎同时发生并导致多个条目进入“预订”>1 日期。我无法在调用 .Commit() 之前进行检查,因为我认为这仍然会导致竞争条件?

我所能看到的只是在提交后进行检查并手动回滚更改,但这让我的嘴巴感觉很糟糕! :)

booking_ref (INT) PRIMARY_KEY AUTOINCREMENT

booking_start (DATETIME)

booking_end (DATETIME)

【问题讨论】:

    标签: sql sql-server nhibernate


    【解决方案1】:
    • 使事务的隔离级别 SERIALIZABLE (session.BeginTransaction(IsolationLevel.Serializable) 并检查并插入同一个事务。一般情况下,您不应该将隔离级别设置为可序列化,只是在这种情况下。

    • 在检查并最终插入之前锁定表。您可以通过 nhibernate 触发 SQL 查询来做到这一点:

      session.CreateSQLQuery("SELECT null as dummy FROM Booking WITH (tablockx, holdlock)").AddScalar("dummy", NHibernateUtil.Int32); 这将在该事务期间仅锁定该表以进行选择/插入。

    希望对你有帮助

    【讨论】:

    • 当然——不敢相信我竟然完全错过了使用表锁,当时脑子一片空白!非常感谢。
    【解决方案2】:

    以上解决方案可以作为一个选项使用。如果我在事务级别可序列化时使用“Parallel.For”发送了 100 个请求,是的,没有重复的请求 ID,但 25 个事务失败。我的客户不能接受。所以我们解决了这个问题,只存储请求 id 并在其他表上添加一个唯一索引作为临时表。

    【讨论】:

      【解决方案3】:

      您的数据库应该管理您的数据完整性。

      您可以使您的“日期”列独一无二。因此,如果 2 个线程尝试获取相同的日期。一个会抛出唯一的密钥违规,另一个会成功。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 2015-09-10
        • 2021-12-07
        • 1970-01-01
        • 2020-07-12
        • 2017-01-23
        相关资源
        最近更新 更多