Некоторая справочная информация:
Данные регулярно обновляются, удаляя старые данные и вставляя новые. Данные группируются в профили, которые я использую как часть первичного ключа и для удаления старых данных.
Только один процесс записывает данные, поэтому вам не нужно беспокоиться о конфликтах обновления кем-то другим.
Другой процесс только считывает данные, которые я планировал решить с помощью Snapshot-Isolation.
Я получаю доступ к данным через сущность framework 6, первое моделирование кода.SQL Concurrent delete locking
Проблема: Я начинаю сбор данных для нескольких профилей параллельно. Работает отлично для всех таблиц с простым отношением внешних ключей, но для одного с самооценкой.
public class Web
{
public Web()
{
CacheDate = DateTime.Now;
}
[Key, Column(Order = 0)]
public Guid ProfileGuid { get; set; }
[Key, Column(Order = 2)]
public Guid WebId { get; set; }
public string Data { get; set; }
public virtual List<List> Lists { get; set; }
public virtual List<Web> SubWebs { get; set; }
public Guid? ParentProfileGuid { get; set; }
public Guid? ParentWebId { get; set; }
public virtual Web ParentWeb { get; set;}
}
modelBuilder.Entity<CacheWeb>()
.HasMany(e => e.SubWebs)
.WithOptional(e => e.ParentWeb)
.HasForeignKey(e => new { e.ParentProfileGuid, e.ParentWebId })
.WillCascadeOnDelete(false);
Из-за проблемы с производительностью я не использовать EF, чтобы удалить данные, но пользовательская SQL команды: InsertContext.Database.ExecuteSqlCommand(String.Format("DELETE FROM Webs WHERE ProfileGuid = '{0}'", profile.Guid));
Если я называю два из этих удалений в параллельных транзакциях, то первый вызов создает замок, который предотвращает продолжение второй транзакции.
Насколько я могу судить, замок каким-то образом связан с индексом самонаведения.
Я только что нашел другое странное поведение, это зависит от того, какая транзакция удаляется первыми. Единственная разница в данных, которые я могу найти, - это глубина отношения родитель-потомок.
Если я запускаю транзакцию Сначала (имеет один родительский элемент и несколько прямых дочерних элементов), я не могу запустить транзакцию B (с некоторыми родительскими - дочерними - дочерними дочерними отношениями), но если я запускаю B, то сначала я могу запустить A без попадая в неприятности с существующими замками.
Есть ли способ решить эту проблему? Или любая идея, что может быть проблемой с замком? Если вам нужна дополнительная информация, прокомментируйте, что именно вам нужно, так как я не совсем уверен, что важно.
EDIT: для разъяснения
BEGIN Transaction t1
DELETE FROM Webs WHERE ProfileGuid = 'b35dbba4-54fc-4df7-b1c8-e559d81dfee3'
BEGIN Transaction t2
DELETE FROM Webs WHERE ProfileGuid = 'b35dbba4-54fc-4df7-b1c8-e559d81dfee4'
работ. Поменяйте порядок, и t1 должен ждать завершения t2.
EDIT3: Модель и полные запросы План выполнения от 3 запроса (удаление CacheList)
BEGIN Transaction t1
DELETE FROM CacheItems WHERE ProfileGuid = 'B35DBBA4-54FC-4DF7-B1C8-E559D81DFEE3'
DELETE FROM CacheFolders WHERE ProfileGuid = 'B35DBBA4-54FC-4DF7-B1C8-E559D81DFEE3'
DELETE FROM CacheLists WHERE ProfileGuid = 'B35DBBA4-54FC-4DF7-B1C8-E559D81DFEE3'
DELETE FROM CacheWebs WHERE ProfileGuid = 'B35DBBA4-54FC-4DF7-B1C8-E559D81DFEE3'
Можно ли запустить трассировку SQL Server с использованием шаблона TSQL_Locks и опубликовать график взаимоблокировки? Это покажет точные данные о тупике. – Vanlightly
Я попробовал, и он ничего не писал в файл событий тупика. Наверное, потому что нет тупика? (никогда не использовал график раньше). Как только я совершаю одну транзакцию, другая работает плавно. Но поскольку одна транзакция может занять до часа ожидания, это не опция. – lolsharp
Вы увидите серию событий, таких как Lock: Deadlock Chain, Deadlock Graph. – Vanlightly