2014-10-16 2 views
0

Использование SQL Server 2008 R2 Я получаю блокировки, когда одновременно выполняется один и тот же оператор обновления (с разными параметрами). Вот тупиковый граф (извините не можете добавлять изображения на здесь же):Slock блокировки сервера с простым оператором обновления

http://i.stack.imgur.com/E6JBK.png

А вот фактический план выполнения:

http://i.stack.imgur.com/emm9i.png

Обновление, как это:

exec sp_executesql N'UPDATE mapping.IssuerAlternateName 
SET 
    UseCount = UseCount + 1, 
    MostRecentlyAppeared = GETDATE(), 
    MostRecentlyAppearedUnderlyingAssetName = @p1 
WHERE ID = @p0 
',N'@p0 int,@p1 nvarchar(4000)',@p0=1234,@p1=N'blah blah blah' 

Если я правильно понял вещи, мы пытаемся читать и писать по тому же индексу (PK_IssuerAlternateName_1).

Есть ли способ разрешить это? Мне было интересно, добавление дополнительного индекса в первичный ключ и использование WITH INDEX может исправить его, остановив чтение PK_IssuerAlternateName_1 (извините, что полное имя усечено в скриншоте плана выполнения).

Или это лучший вариант, чтобы жить с этим и повторить транзакцию, как это происходит в настоящее время в .NET-клиенте. Это, безусловно, успешное повторение, но было бы неплохо избежать тупиковой ситуации, если это возможно.

Благодаря

+0

В настоящее время вы свертываете это с транзакцией? Если да, то какой уровень изоляции вы используете? – mallocation

+0

Вызов его с использованием LINQ2SQL, поэтому context.ExecuteCommand() ... – MT1

ответ

0

В ситуациях, подобных этому, я использовал UPDLOCK намек, чтобы база данных знают, что я намерен обновить эту строку. Это не подразумевается в заявлении UPDATE. Без подсказки блокировки он сначала получит «общий» замок, а затем попытается обойтись. Однако это вызывает блокировки в определенных сценариях.

Вам нужно будет сделать это в пределах вашего собственного TransactionScope, чтобы все работало правильно.

var sql = @"UPDATE mapping.IssuerAlternateName with (UPDLOCK) 
SET 
    UseCount = UseCount + 1, 
    MostRecentlyAppeared = GETDATE(), 
    MostRecentlyAppearedUnderlyingAssetName = @p1 
WHERE ID = @p0"; 

var options = new TransactionOptions() 
{ 
    IsolationLevel = IsolationLevel.ReadCommitted // don't use Serializable! 
}; 

using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, options)) 
{ 
    using (var context = new YourDbContext()) 
    { 
     // execute your command here 
    } 
} 
+0

Итак, если он получает блокировку обновления, а не общую блокировку, следующий процесс просто дождитесь завершения этого утверждения перед запуском? Извините, я не DBA ... – MT1

+0

Да. И я тоже не администратор базы данных. У меня только что был подобный опыт в среде очереди. – mallocation

Смежные вопросы