Как несколько хранимых процедур могут обновлять одну и ту же строку одновременно? - PullRequest
0 голосов
/ 07 августа 2010

Я использую SSIS 2008 для параллельного выполнения нескольких хранимых процедур в потоке управления. Предполагается, что каждый SP в конечном итоге обновит 1 строку в таблице.

Следует отметить, что каждый SP имеет определенную ответственность за обновление только определенных столбцов.

Гарантируется, что разные SP не будут обновлять столбцы друг друга. Таким образом, столбцы, подлежащие обновлению, разделены между различными SP, но в соответствии с проектом каждый SP должен в конечном итоге работать в одной строке.

В данный момент некоторые из моих SP-систем вышли из-за тупика. Я предполагаю, что это может быть из-за блокировки в этом ряду другими SP?

Как я могу решить это?

Ответы [ 5 ]

1 голос
/ 07 августа 2010

Вы должны признать, что это очень необычная вещь.Интересно, не лучше ли обновить отдельные таблицы, а затем добавить в конце один оператор обновления, который бы объединял отдельные таблицы с финальными?(т.е. update a set a.[1] = ... from a inner join b inner join c и т. д.).

Но, если вы хотите продолжить этот путь, просто установите READ UNCOMMITTED в каждой из ваших хранимых процедур.Это лучшая ставка.

1 голос
/ 07 августа 2010

Возможно, взаимоблокировки вызваны не только тем, что другой SP блокирует строку.В этой ситуации первая процедура будет просто ждать, пока блокирующий SP не снимет блокировку.Это не означает, что ваши многочисленные процедуры не вызывают проблемы.Хотя это еще не все.

Возможно, вам придется сделать некоторые переделки, чтобы избежать проблемы, но сначала вы должны узнать больше о тупиковой ситуации.Я подозреваю, что у вас есть блокировки на объектах, кроме строки, которая обновляется.

Есть способы собрать больше информации о тупике.Вот ссылка , где вы можете узнать подробности тупика.

0 голосов
/ 07 августа 2010

Нет, два сеанса не могут обновлять одну и ту же строку одновременно.Блокировка на уровне строк настолько низка, насколько это возможно, когда один сеанс обновляет строку, другие сеансы, желающие обновить эту запись, будут ждать.

Что касается взаимоблокировок, проблема с SQL Server заключается в том, что по умолчанию операторы SELECTбудет заблокирован, если он запрашивает запись, которая в данный момент обновляется.Вы можете использовать WITH (NOLOCK), если не возражаете против чтения незафиксированных данных.

Итак, если у вас есть такой порядок событий: SessionA

begin transaction

update t1
set c1 = 'x'
where c2 = 5

SessionB

begin transaction

update t2 
set c1 = 'y'
where c2 = 7

SessionA

select * from t1 where c2 = 5
<waits on SessionB>

SessionB
select * from t2 where c2 = 7
<waits on SessionA>...oops. Deadlock.

Хитрость заключается только взаблокируйте что-то на минимальное время, необходимое для этого (не разбивайте последовательность операторов только для снятия блокировки - убедитесь, что шаги, составляющие логическую транзакцию, остаются транзакцией):

begin transaction

update t1
set c1 = 'x'
where c2 = 5

commit

Или (caveat emptor) используйте директиву nolock:

SessionA

select c1 from t1 where c2 = 5 with (nolock)
<gets the new value of 'x'>

SessionB
select * from t2 where c2 = 7 with (nolock)
<gets the new value of 'y'>
0 голосов
/ 07 августа 2010

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

0 голосов
/ 07 августа 2010

Просто: сделай так, чтобы ты нигде не оставлял замки.Это работает с изоляцией транзакции, определенной соединением.При правильной идентификации транзакций блокировок не будет, поэтому не будет взаимоблокировок.

Обновление не является проблемой.Это начинается с ЧИТАЕТ.Перейдите к READ UNCOMMITED, чтобы убедиться, что вы не оставляете блокировки при чтении, и / или используйте опцию NOLOCK в операторах SELECT, чтобы по отдельности заставить их оставлять NO LOCKS вместо данных чтения (более целесообразно).Если вы затем убедитесь, что SP выполнит коммит в значительной степени сразу после вставки (внутренне или внешне), тупиковая блокировка невозможна - блокировка записи приведет к тому, что следующий SP ожидает первой транзакции для фиксации.

Особенно при переходе к одной таблице / одной строке тупик невозможен только с операторами обновления, IIRC.Это блокировки чтения, которые превращают задерживающую блокировку (хотя и небольшую задержку) в тупик.

http://www.eggheadcafe.com/software/aspnet/30976898/how-does-update-lock-prevent-deadlocks.aspx имеет хороший пример тупика.Итак, если все, НО в обновлении нет блокировок, то в конце тупик невозможен.

...