【问题标题】:Concurrency And Locking Across Load Balanced Application跨负载均衡应用程序的并发和锁定
【发布时间】:2019-08-12 14:48:44
【问题描述】:

我正在编写一个应用程序,用户可以在其中创建具有开始日期和结束日期的项目,并将它们保存到 Microsoft Sql Server 中托管的 SQL 数据库中。应用程序中的规则是在给定时间内只能激活单个项目(没有重叠项目)。该应用程序还需要负载平衡,这意味着(据我所知)传统的信号量/锁定将不起作用。

一些额外的项目:

  • 记录保存在两个表中(根据业务需求)。
  • 允许用户在现有记录的中间“插入”记录。插入的记录会调整任何预先存在的记录的开始和结束日期,以防止项目重叠(如有必要)。
  • 理想情况下,我们希望使用我们的 ORM 和 .Net 来完成此任务。我们没有太多的余地来更改数据库模式,但我们可以通过 ORM 创建事务并执行其他类型的 SQL 操作。

我们的目标是防止以下情况发生:

  • 来自多个用户的保存导致任一表中的项目重叠(例如,用户 1 和 2 查询数据库,查看没有重叠记录,并同时保存)
  • 来自多个用户的保存导致每个目标表中的状态不同(例如,两个用户“插入”记录,并且操作在两个表之间交错。表 A 看起来好像用户 1 先行,表B 看起来好像是用户 2 先走。)

我的问题是如何锁定或阻止多个用户在负载平衡的服务器上同时保存/插入。

注意:我们目前正在研究使用 sp_getapplock,因为它似乎可以满足我们的需求,如果您有这方面的经验或觉得这是一个错误的决定,并且想要详细说明,我们也将不胜感激!

编辑:添加了附加信息

【问题讨论】:

  • 您所说的 Microsoft SQL 是什么意思?您是在谈论 Microsoft SQL Server - 完全关系型 db mgmt 系统 - 还是在谈论 Microsoft Access with SQL - 基于文件的数据库“系统”来自 Microsoft 并且会说 SQL:...您对此不清楚 - 请让我们更清楚!
  • 对不起,Microsoft Sql Server!
  • 事务中的 sp_getapplock 和看起来一样好。比依靠行/页锁定来实现这种应用程序逻辑要简单得多。但是您希望 DRI 或触发器实际执行这些规则。

标签: c# asp.net sql-server concurrency locking


【解决方案1】:

至少有两种选择:

  • 您可以创建一个将 INSERT 操作包装在事务中的存储过程:

    begin tran
        select to see if there is an existing record
        you can:
            - invalidate the previous record
            - insert a new record
        or
            - raise an error
        commit tran
    catch error
        rollback tran
    
  • 您可以采用“后进胜出”策略,即不采用写级锁,而是采用读级伪锁,基本上忽略除最新记录之外的所有记录。

【讨论】:

    猜你喜欢
    • 2018-10-15
    • 2020-02-25
    • 2012-01-11
    • 2017-09-27
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    相关资源
    最近更新 更多