Насколько завершен стэк выполнения графа взаимоблокировки SQL Server 2008? - PullRequest
3 голосов
/ 26 мая 2011

Когда я получаю график взаимоблокировки xml в SQL Server, он показывает мне стек выполнения для каждого процесса, например, (Я удалил большинство атрибутов):

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

Я знаю, что список кадров не содержит все кадры в транзакции, но содержит ли он все кадры, которые вовлечены в тупик, поэтому мне не нужно искать дальше? Или мне нужно также изучить предыдущие SQL-операторы в той же транзакции, чтобы получить полное представление о причине тупика?

Редактировать: чтобы уточнить, следующее может заблокировать себя, если выполняется в двух отдельных спидах:

выберите * из таблицы, где column = @arg удалить из mytable, где column = @ arg

Будет ли на графике взаимоблокировки показан оператор выбора, а также оператор удаления, или только оператор удаления, поскольку это был последний оператор в транзакции? Не видя также оператора select, трудно определить правильное исправление (например, подсказка по обновлению выбора).

1 Ответ

3 голосов
/ 30 октября 2011

Вам необходимо проверить предыдущие 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 (выполняется быстро после соединения 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, который получил блокировки в первую очередь, не отображаются.

(NB: без оператора GO для разделения операторов на отдельные пакеты в этом случае вы бы увидели оператор, нарушающий работу, но в целом получение блокировки может происходить дальше по стеку вызовов, поэтому оператор, который фактически получил блокировки, все равно не будет не будет показано)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...