Ошибка тупика сервера SQL при выполнении нескольких вставок в хранимой процедуре - PullRequest
1 голос
/ 04 февраля 2012

Я сталкиваюсь с проблемой взаимоблокировки, когда моя хранимая процедура вызывается в sql server 2008. Строка xml передается в хранимую процедуру biztalk и может быть вызвана много раз подряд.Проблема, с которой я сталкиваюсь, заключается в том, что если процедура вызывается 5 раз подряд, первые 4 вызова откатываются, и последний вызов фиксируется в базе данных из-за тупика.Ниже приведен код процедуры - он использует OPENXML для анализа строки xml и вставки в таблицу A. Затем я беру новый уникальный идентификатор из таблицы A и вставляю несколько дочерних записей в таблицу B. Любое руководство по решению этой проблемы будетприветствуем.

Сообщение об ошибке: System.Data.SqlClient.SqlException (0x80131904): Транзакция (идентификатор процесса XX) заблокирована для ресурсов блокировки с другим процессом и была выбрана в качествежертва тупика.Перезапустите транзакцию.

Подробности таблицы TableA- Id int identity (1,1) Первичный ключ,- Столбец А varchar (15) не нулевой,- ColumnB varchar (20) не нуль,- AddedDateTime datetime по умолчанию (getdate ())

Таблица B- Id int identity (1,1) Первичный ключ,- TableAId int не null, (FK)- ColumnC varchar (30) не является нулевым

XML

<Transactions>
<Transaction>
    <ColumnA>Column A Value</ColumnA>
    <ColumnB>Column B Value</ColumnB>
    <ChildItems>
        <ChildItem>
            <ColumnC>Column C Value</ColumnC>
        </ChildItem>
        <ChildItem>
            <ColumnC>Another Column C Value</ColumnC>
        </ChildItem>
        <ChildItem>
            <ColumnC>Yet Another Column C Value</ColumnC>
        </ChildItem>
    </ChildItems>

Хранимая процедура

 CREATE PROCEDURE [dbo].[proc_ProcessXml] 
    (
        @ResponseXml varchar(max)
    )
    WITH EXECUTE AS CALLER  
    AS

    BEGIN TRANSACTION
    DECLARE @xmlHandle int
    declare @tableAId int

    EXEC sp_xml_preparedocument @xmlHandle OUTPUT, @ResponseXml, 

    INSERT INTO TableA 
    (
        ColumnA,
        ColumnB             
   ) 
   SELECT columnA, columnB
    FROM OPENXML(@xmlHandle, '/Transactions/Transaction', 1)
    WITH(
        columnA varchar(15) 'ColumnA',      
        columnB varchar(20) 'ColumnB'
    )

    select @tableAId = SCOPE_IDENTITY()

    INSERT INTO TableB 
    (
        TableAId,
        ColumnC             
    )  
    SELECT @tableAId, columnC
    FROM OPENXML(@xmlHandle, '/Transactions/Transaction/ChildItems/ChildItem', 1) 
    WITH(       
        columnC varchar(30) 'ColumnC',
    )

    EXEC sp_xml_removedocument @xmlHandle

    IF @@ERROR <> 0
        BEGIN                   
            ROLLBACK
        END
    ELSE
        BEGIN           
            COMMIT
        END

1 Ответ

1 голос
/ 05 февраля 2012

Может быть много разных причин для такого поведения, поэтому вам нужно получить больше фактов.Вы должны знать уровни изоляции и замки, за которые они борются.Вот что я бы сделал:

  1. Подготовьте четыре окна в Mgmt Studio для вызова вашего процесса
  2. Проверьте Уровни изоляции каждого звонящего прямо перед его вызовомproc (dbcc useroptions).
  3. Определите spid четырех вызывающих абонентов (@@ spid)
  4. Сделайте снимок всех блокировок перед началом ваших тестов с пятого сеанса:

.

select
     object_name(P.object_id) as TableName, L.*
into
    #preTestLocks
from     
    sys.dm_tran_locks L
    join sys.partitions P on L.resource_associated_entity_id = p.hobt_id
where
     object_name(P.object_id) in ('TableA','TableB')
  1. Добавьте ожидание в процедуре после вставки TableA (WAYITFOR DELAY '00: 00: 30 ′), чтобы вы могли смотреть на вещи в движении.
  2. Запускать процесс в каждом сеансе, но после каждого запуска делать снимок блокировок из вашего пятого окна:

.

select
     object_name(P.object_id) as TableName, L.*
into
    #lock1  --<<CHANGE AFTER EACH RUN (#lock2, #lock3 etc.)
from     
    sys.dm_tran_locks L
    join sys.partitions P on L.resource_associated_entity_id = p.hobt_id
where
    resource_session_id in (1,2,3,4) --<<YOUR SPID'S

Анализировать результатыи посмотрите, какие ресурсы вызывают состояние тупика.У вас могут возникнуть проблемы с эскалацией блокировок, которые приводят к эскалации блокировок на уровне строк на странице, расширении или даже на уровне таблиц. Прочтите здесь описание режимов блокировки .

Последнее замечание:

Возможно, вы играете с огнем, начав транзакцию внутри процедуры и не указав SET XACT_ABORT ON( Подробнее см. Здесь ).Я сомневаюсь, что это вызывает ваше текущее поведение, если ваши клиенты не имеют удивительно короткие тайм-ауты, но я настоятельно рекомендую добавить это.

...