SQL Server 2008死锁图执行堆栈的完整性如何?

发布于 2024-11-10 09:49:35 字数 673 浏览 3 评论 0原文

当我在 SQL Server 中获取死锁图 xml 时,它向我显示每个进程的执行堆栈,例如(我已删除大部分属性):

<process>
<executionStack>
    <frame>INSERT INTO MYTABLE</frame>
    <frame>INSERT INTO MYTABLE</frame>
</executionStack>
<inputbuf>INSERT INTO MYTABLE</inputbuf>
</process>

我知道帧列表不包含事务中的所有帧,但它确实如此吗?包含与死锁有关的所有帧,因此我不需要再进一步查看?或者我是否还需要检查同一事务中前面的 sql 语句以全面了解死锁的原因?

编辑:为了进一步澄清,如果在两个单独的 spid 中运行,以下代码可能会导致自身死锁:

select * from mytable where column = @arg delete from mytable where column = @arg

死锁图会显示 select 语句以及删除语句,还是仅显示删除语句,因为它是事务中的最后一个语句?如果没有看到 select 语句,就很难确定正确的修复(例如,select 上的 updlock 提示)。

When I get the deadlock graph xml in SQL Server, it shows me an executionStack for each process, e.g. (I have removed most of the attributes):

<process>
<executionStack>
    <frame>INSERT INTO MYTABLE</frame>
    <frame>INSERT INTO MYTABLE</frame>
</executionStack>
<inputbuf>INSERT INTO MYTABLE</inputbuf>
</process>

I know the list of frames does not contain all the frames in the transaction, but does it contain all the frames that are implicated in the deadlock, so I do not need to look any further? Or do I need to also examine the preceding sql statements in the same transaction to get a complete picture as to the cause of the deadlock?

Edit: to clarify further, the following can deadlock itself if run in two separate spids:

select * from mytable where column = @arg
delete from mytable where column = @arg

Will the deadlock graph show the select statement as well as the delete statement, or only the delete statement because that was the last statement in the transaction? Without seeing the select statement too, it is difficult to identify the correct fix (e.g., updlock hint on the select).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你的呼吸 2024-11-17 09:49:35

您需要在同一事务中检查前面的sql语句。

死锁图仅显示发生死锁时执行的语句的调用堆栈。实际获取死锁资源的语句可能不存在。这很容易证明如下。

连接 1

CREATE TABLE T1
  (
     id  INT PRIMARY KEY,
     foo CHAR(100),
     bar CHAR(100)
  )

INSERT INTO T1
            (id)
VALUES     (1),
            (2)

GO

BEGIN TRAN

UPDATE T1
SET    foo = '123'
WHERE  id = 1

WAITFOR DELAY '00:00:05'

GO

UPDATE T1
SET    bar = 'dlock'
WHERE  id = 2

ROLLBACK

DROP TABLE T1 

连接 2(在 Conn 1 之后快速执行)

BEGIN TRAN

UPDATE T1
SET    foo = '123'
WHERE  id = 2

WAITFOR DELAY '00:00:05'

GO

UPDATE T1
SET    bar = 'dlock'
WHERE  id = 1

ROLLBACK 

死锁图

<process-list>
    <process
        id="process520d1c8"
        taskpriority="0"
        logused="504"
        waitresource="KEY: 1:72057594051100672 (010086470766)"
        waittime="3666"
        ownerId="10399789"
        transactionname="user_transaction"
        lasttranstarted="2011-10-30T13:45:29.030"
        XDES="0x4eb5be8"
        lockMode="X"
        schedulerid="2"
        kpid="8656"
        status="suspended"
        spid="59"
        sbid="0"
        ecid="0"
        priority="0"
        trancount="2"
        lastbatchstarted="2011-10-30T13:45:34.047"
        lastbatchcompleted="2011-10-30T13:45:34.043"
        clientapp="Microsoft SQL Server Management Studio - Query"
        hostname="MyPC"
        hostpid="7544"
        loginname="Me"
        isolationlevel="read committed (2)"
        xactid="10399789"
        currentdb="1"
        lockTimeout="4294967295"
        clientoption1="671090784"
        clientoption2="390200">
        <executionStack>
            <frame
                procname="adhoc"
                line="2"
                stmtstart="58"
                sqlhandle="0x02000000b24eb7001f552b64e5c2bf2ccb1f2acfda154410">
            UPDATE [T1] set [bar] = @1  WHERE [id]=@2
          </frame>
            <frame
                procname="adhoc"
                line="2"
                stmtstart="4"
                stmtend="90"
                sqlhandle="0x020000002688730e96c94af4582dfb097fa79a39ea620d63">
            UPDATE T1 SET bar = 'dlock' where id=1
          </frame>
        </executionStack>
        <inputbuf>

          UPDATE T1 SET bar = 'dlock' where id=1


          rollback
        </inputbuf>
    </process>
    <process
        id="process370d8718"
        taskpriority="0"
        logused="504"
        waitresource="KEY: 1:72057594051100672 (020068e8b274)"
        waittime="5579"
        ownerId="10399738"
        transactionname="user_transaction"
        lasttranstarted="2011-10-30T13:45:27.040"
        XDES="0x1ef7ac10"
        lockMode="X"
        schedulerid="1"
        kpid="2060"
        status="suspended"
        spid="52"
        sbid="0"
        ecid="0"
        priority="0"
        trancount="2"
        lastbatchstarted="2011-10-30T13:45:32.083"
        lastbatchcompleted="2011-10-30T13:45:32.043"
        clientapp="Microsoft SQL Server Management Studio - Query"
        hostname="MyPC"
        hostpid="7544"
        loginname="Me"
        isolationlevel="read committed (2)"
        xactid="10399738"
        currentdb="1"
        lockTimeout="4294967295"
        clientoption1="671098976"
        clientoption2="390200">
        <executionStack>
            <frame
                procname="adhoc"
                line="3"
                stmtstart="58"
                sqlhandle="0x02000000b24eb7001f552b64e5c2bf2ccb1f2acfda154410">
            UPDATE [T1] set [bar] = @1  WHERE [id]=@2
          </frame>
            <frame
                procname="adhoc"
                line="3"
                stmtstart="8"
                stmtend="94"
                sqlhandle="0x020000004a869b267636c00306e481791dec78ade36b3f39">
            UPDATE T1 SET bar = 'dlock' where id=2
          </frame>
        </executionStack>
        <inputbuf>


          UPDATE T1 SET bar = 'dlock' where id=2


          ROLLBACK

          DROP TABLE T1
        </inputbuf>
    </process>
</process-list>

未显示对首先获取锁的列 foo 的分配。

(注意:如果没有 GO 语句来使语句分开批次,在这种情况下,您会看到有问题的语句,但一般来说,锁获取可能发生在调用堆栈的更下方,因此实际获取锁的语句仍然不会显示)

You need to examine the preceding sql statements in the same transaction.

The deadlock graph just shows you the call stack for the statements executing when the deadlock occurred. The statements that actually acquired the deadlocked resources may not be present. This is easily demonstrated as follows.

Connection 1

CREATE TABLE T1
  (
     id  INT PRIMARY KEY,
     foo CHAR(100),
     bar CHAR(100)
  )

INSERT INTO T1
            (id)
VALUES     (1),
            (2)

GO

BEGIN TRAN

UPDATE T1
SET    foo = '123'
WHERE  id = 1

WAITFOR DELAY '00:00:05'

GO

UPDATE T1
SET    bar = 'dlock'
WHERE  id = 2

ROLLBACK

DROP TABLE T1 

Connection 2 (Execute quickly after Conn 1)

BEGIN TRAN

UPDATE T1
SET    foo = '123'
WHERE  id = 2

WAITFOR DELAY '00:00:05'

GO

UPDATE T1
SET    bar = 'dlock'
WHERE  id = 1

ROLLBACK 

Deadlock Graph

<process-list>
    <process
        id="process520d1c8"
        taskpriority="0"
        logused="504"
        waitresource="KEY: 1:72057594051100672 (010086470766)"
        waittime="3666"
        ownerId="10399789"
        transactionname="user_transaction"
        lasttranstarted="2011-10-30T13:45:29.030"
        XDES="0x4eb5be8"
        lockMode="X"
        schedulerid="2"
        kpid="8656"
        status="suspended"
        spid="59"
        sbid="0"
        ecid="0"
        priority="0"
        trancount="2"
        lastbatchstarted="2011-10-30T13:45:34.047"
        lastbatchcompleted="2011-10-30T13:45:34.043"
        clientapp="Microsoft SQL Server Management Studio - Query"
        hostname="MyPC"
        hostpid="7544"
        loginname="Me"
        isolationlevel="read committed (2)"
        xactid="10399789"
        currentdb="1"
        lockTimeout="4294967295"
        clientoption1="671090784"
        clientoption2="390200">
        <executionStack>
            <frame
                procname="adhoc"
                line="2"
                stmtstart="58"
                sqlhandle="0x02000000b24eb7001f552b64e5c2bf2ccb1f2acfda154410">
            UPDATE [T1] set [bar] = @1  WHERE [id]=@2
          </frame>
            <frame
                procname="adhoc"
                line="2"
                stmtstart="4"
                stmtend="90"
                sqlhandle="0x020000002688730e96c94af4582dfb097fa79a39ea620d63">
            UPDATE T1 SET bar = 'dlock' where id=1
          </frame>
        </executionStack>
        <inputbuf>

          UPDATE T1 SET bar = 'dlock' where id=1


          rollback
        </inputbuf>
    </process>
    <process
        id="process370d8718"
        taskpriority="0"
        logused="504"
        waitresource="KEY: 1:72057594051100672 (020068e8b274)"
        waittime="5579"
        ownerId="10399738"
        transactionname="user_transaction"
        lasttranstarted="2011-10-30T13:45:27.040"
        XDES="0x1ef7ac10"
        lockMode="X"
        schedulerid="1"
        kpid="2060"
        status="suspended"
        spid="52"
        sbid="0"
        ecid="0"
        priority="0"
        trancount="2"
        lastbatchstarted="2011-10-30T13:45:32.083"
        lastbatchcompleted="2011-10-30T13:45:32.043"
        clientapp="Microsoft SQL Server Management Studio - Query"
        hostname="MyPC"
        hostpid="7544"
        loginname="Me"
        isolationlevel="read committed (2)"
        xactid="10399738"
        currentdb="1"
        lockTimeout="4294967295"
        clientoption1="671098976"
        clientoption2="390200">
        <executionStack>
            <frame
                procname="adhoc"
                line="3"
                stmtstart="58"
                sqlhandle="0x02000000b24eb7001f552b64e5c2bf2ccb1f2acfda154410">
            UPDATE [T1] set [bar] = @1  WHERE [id]=@2
          </frame>
            <frame
                procname="adhoc"
                line="3"
                stmtstart="8"
                stmtend="94"
                sqlhandle="0x020000004a869b267636c00306e481791dec78ade36b3f39">
            UPDATE T1 SET bar = 'dlock' where id=2
          </frame>
        </executionStack>
        <inputbuf>


          UPDATE T1 SET bar = 'dlock' where id=2


          ROLLBACK

          DROP TABLE T1
        </inputbuf>
    </process>
</process-list>

The assignments to column foo that acquired the locks in the first place aren't shown.

(NB: Without the GO statement to make the statements separate batches you would in this case see the offending statement but in general the lock acquisition might occur further down the call stack so the statement that actually acquired the locks still wouldn't be shown)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文