【问题标题】:LOCK HINT MS-SQL Server, Slick and Scala锁定提示 MS-SQL Server、Slick 和 Scala
【发布时间】:2020-10-23 06:39:28
【问题描述】:

我正在尝试在我的应用程序中运行以下查询。有人可以解释一下如果 2 个线程尝试选择同一行会发生什么,因为显然在以下所有提示中都允许选择。我们在事务中看到很多死锁,首先获取这个锁并做一些事情。谢谢!

select  a, b, c, d, created_time, updated_time
          from lock_table
              with (ROWLOCK,UPDLOCK,HOLDLOCK)
               where a = $a
               AND b = $b
               AND c = $c
               AND d = $d.as[LockTableDetails]

【问题讨论】:

    标签: sql-server scala slick


    【解决方案1】:

    有人可以解释一下如果 2 个线程尝试选择同一行会发生什么

    假设

    1. 两个会话都在此声明之前开始了transaction
    2. 两个会话提供完全相同的参数值 和
    3. 两个会话都使用读取相同索引的查询计划

    第一个会话将在查询读取的索引的每一行上获取一个更新 (U) 锁(如果没有匹配的行,可能还有一个范围锁)。这些锁将在事务期间保持,第二个会话将阻塞。

    如果您在这里看到意外的并发执行,可能是因为您没有使用参数,而是使用了 Scala 字符串插值。当您将字符串粘贴到 SQL 查询中时,两个会话将发送 不同 查询以获得 不同 执行计划、锁定 不同 索引并继续死锁。

    查询应该使用参数,例如:

    select  a, b, c, d, created_time, updated_time
              from lock_table
                  with (ROWLOCK,UPDLOCK,HOLDLOCK)
                   where a = @a
                   AND b = @b
                   AND c = @c
                   AND d = @d.as[LockTableDetails]
    

    并使用preparedStatement 执行。然后会话实际上将执行 same 查询,并且将获得相同的执行计划。

    如果这不能解决死锁,请发布死锁 XML 和有关并发事务的其他详细信息。

    【讨论】:

    • 我使用 sql 插值器。所以,代码有点像:sql"""select a, b, c, d, created_time, updated_time from lock_table with (ROWLOCK,UPDLOCK,HOLDLOCK) where a = $a AND b = $b AND c = $c AND d = $d""".as[LockTableDetails]
    • 然后发布死锁 XML。它会显示是否发生参数替换,以及死锁的原因。
    • 解决了这个问题。由于插入速度慢,表上定义了太多索引。因此,不应该长时间在同一页面上的数据会保留在那里,并且来自应用程序不同线程的选择查询会导致死锁。
    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 2013-09-23
    • 1970-01-01
    相关资源
    最近更新 更多