【问题标题】:sql server 2008 Deadlock in two parallel transactionssql server 2008 两个并行事务中的死锁
【发布时间】:2013-01-12 20:45:57
【问题描述】:

我有两个事务:具有SERIALIZABLE 隔离级别的 T1 和 T2(我认为 - 具有默认的 READ COMMITTED 隔离级别,但没关系)。

事务 T1 执行 SELECT 然后 WAITFOR 2 秒然后 SELECT

事务 T2 对 T1 读取的数据执行UPDATE

导致死锁,为什么事务T2不等待T1结束?

当 T1 具有 REPEATABLE READ 隔离级别时,一切正常,即出现幻像行。 我想当我将隔离级别提高到SERIALIZABLE 时,T2 将等待 T1 结束。

这是我大学练习的一部分。我必须在两个具有不正确隔离级别的并行事务中显示负面影响,并且在正确的隔离级别下不存在这些影响。

这是代码,遗憾的是字段名称是波兰语。

T1:

使用先生; SET IMPLICIT_TRANSACTIONS 关闭; 设置事务隔离级别可序列化; 开始交易; -- 1. 扎皮塔尼 选择 www.IdSamochodu, s.Model, s.Marka, s.NrRejestracyjny, o.PESEL, o.Nazwisko, o.Imie, o.NrTelefonu 从 WizytyWWarsztacie www 加入 萨摩奇 ON s.IdSamochodu = www.IdSamochodu 加入 奥索比 ON o.PESEL = s.PESEL 在哪里 www.[状态] = 'gotowy_do_odbioru' 由 www.IdSamochodu ASC 订购 ; 等待延迟'00:00:02'; -- 2. 扎皮塔尼 选择 u.IdSamochodu,tu.Nazwa,tu.Opis,u.Oplata 从 乌斯鲁吉乌 加入 TypyUslug tu ON tu.IdTypuUslugi = u.IdTypuUslugi 加入 WizytyWWarsztacie www 在 www.IdSamochodu = u.IdSamochodu 和 www.DataOd = u.DataOd 在哪里 www.[状态] = 'gotowy_do_odbioru' 由 u.IdSamochodu ASC、u.Oplata DESC 订购 ; 犯罪;

T2:

使用先生; SET IMPLICIT_TRANSACTIONS 关闭; 将事务隔离级别设置为已提交; 开始交易; 更新 乌斯鲁吉 放 [状态] = 'wykonano' 在哪里 IdUslugi = 2 ; 更新 万维网 放 www.[状态] = 'gotowy_do_odbioru' 从 WizytyWWarsztacie www 在哪里 www.[状态] = 'wykonywanie_usług' AND 存在( 选择 1 从 乌斯鲁吉乌 在哪里 u.IdSamochodu = www.IdSamochodu 和 u.DataOd = www.DataOd AND u.[状态] = 'wykonano' 由 u.IdSamochodu、u.DataOd 分组 有计数(u.IdUslugi)=( 选择 计数(u2.IdUslugi) 从 乌斯鲁吉 u2 在哪里 u2.IdSamochodu = www.IdSamochodu 和 u2.DataOd = www.DataOd 由 u2.IdSamochodu、u2.DataOd 分组 ) ) ; 犯罪;

我使用 SQL Management Studio,每个事务都在不同的文件中。我通过在 T1 中单击 F5 来运行它,然后快速切换到包含 T2 的文件,然后再次 - F5。

我阅读了 mssql 中的死锁和锁定机制,但显然我还没有理解这个主题。

Deadlock issue in SQL Server 2008 R2 (.Net 2.0 Application)

SQL Server deadlocks between select/update or multiple selects

Deadlock on SELECT/UPDATE

http://msdn.microsoft.com/en-us/library/ms173763(v=sql.105).aspx

http://www.sql-server-performance.com/2004/advanced-sql-locking/

编辑

我发现 T2 中的第一个 UPDATE 语句会导致问题,为什么?

【问题讨论】:

  • 请提供表定义,包括索引和SELECTUPDATE 查询。
  • 如果您发布代码/查询,您将获得更好的指导。我特别想知道您所说的并行事务是什么意思(您的查询代码/批处理将帮助我弄清楚)。

标签: sql sql-server database deadlock


【解决方案1】:

解决死锁问题从获取死锁图开始。这是一个 xml 文档,它告诉您有关所涉及的事务和资源的相关信息。您可以通过 Profiler、扩展事件或事件通知来获取它(我确信还有其他方法,但现在就可以了)。获得图表后,检查它以查看每个事务在哪些资源上具有什么类型的锁。你从那里去哪里真的取决于图表中发生的事情,所以我会停在那里。底线:获取死锁图并挖掘它以获取详细信息。

顺便说一句,说一个或另一个事务“导致”死锁有点误导。死锁中涉及的所有事务都是导致死锁情况所必需的,因此两者都没有更多的错误。

【讨论】:

  • 感谢您的提示,我不知道 Profiler 和死锁图之类的东西。我是 MS SQL Server 的新手。
  • 不用担心。这就是任何事情的伟大之处:每个人一开始都一无所知。 :)
【解决方案2】:

我的 SQL Managmenet Studio 出现了一些问题(Profiler 没有工作),但最后我获得了死锁图This article 对我很有帮助。

要理解这个图表,我必须了解锁定机制和符号。
我觉得here解释的很清楚。

现在,当我知道所有这些东西时,死锁的原因就很明显了。
我已经为所描述的情况制作了序列图:

正如我之前写的,当我们从事务 T2 中删除第一个 UPDATE 语句时,不会发生死锁。

在这种情况下,T2 不会在 pk_uslugi 索引上获得锁,因此事务 T1 中的第二个 SELECT 语句将成功执行,并且索引 pk_wizytywwarsztacie 将被解锁。之后T2也完成了。

【讨论】:

    【解决方案3】:

    问题可能是这样的:

    1. T1 Select S 锁定行
    2. T2 更新 U 锁定行(成功)
    3. T2 更新 X 锁定行(等待,锁定排队)
    4. T2 再次尝试 S-lock,但 S-lock 与排队的 X-lock 不兼容。

    SQL Server 中的锁已排队。如果队列的头在等待,它后面的所有其他东西也会等待。

    实际上,我不完全确定这就是原因,因为REPEATABLE READ 会出现同样的问题应该。我仍在发布这个想法,希望对您有所帮助。

    【讨论】:

      【解决方案4】:

      我遇到了类似的问题,我从可用项目列表中进行选择,然后将这些项目插入到保留队列表中。当我有太多并发请求时,select 语句将返回在另一个并行请求期间也同时选择的项目。当尝试将它们插入到保留队列表中时,我会收到一个唯一约束错误(因为同一个项目不能两次进入保留表)。

      然后我尝试将 SERIALIZABLE 事务包装在整个事情上,但后来我遇到了 DEADLOCK 错误,因为两个事务都持有 UC 索引上的锁(由我的死锁图确定)。

      我终于能够通过在 select 语句中使用排他行锁来解决问题

      您可以尝试在有问题的表/行上使用排他行锁。这将确保 T1 中的行锁定将在 T2 尝试更新相同的行之前完成。

      示例:

      SELECT *
      FROM Uslugi u WITH (XLOCK, ROWLOCK)
      

      我还不确定这对性能的影响,但在使用多线程运行负载测试时,它似乎没有负面影响。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多