Операция изоляции моментальных снимков отменена из-за конфликта обновлений
Следующее утверждение:
INSERT INTO dbo.Changes([Content], [Date], [UserId], [CompanyId])
VALUES (@1, @2, @3, @4);
SELECT @@identity;
дает мне эту ошибку SQL 3960:
Операция изоляции моментальных снимков отменена из-за конфликта обновлений. Вы не может использовать изоляцию моментальных снимков для прямого доступа к таблице "dbo.Companies" или косвенно в базе данных "myDatabase" для обновления, удаления или вставки строка, которая была изменена или удалена другой транзакцией. Повторите транзакцию или измените уровень изоляции для update/delete.
Насколько я понял, из сообщения об ошибке я не должен обновлять, удалять или вставлять в таблицу dbo.Companies
в то время, когда изменяется другое соединение dbo.Companies
.
Но почему это происходит, когда я вставлял новую строку в другую таблицу dbo.Changes
(у которой есть внешний ключ для dbo.Companies
), и я не удалял ссылочную строку в dbo.Companies
, но я просто обновлял строку в dbo.Companies
, а не первичный ключ? Это должно работать нормально, не так ли? (Это ошибка в SQL Server?)
ОБНОВЛЕНИЕ:
Таблицы выглядят следующим образом:
dbo.Changes([Id] int PK, [Content] nvarchar,
[Date] datetime, [UserId] int, [CompanyId] int -> dbo.Companies.[Id])
dbo.Companies([Id] int PK, [Name] nvarchar)
Выполняется второе обновление:
UPDATE dbo.Companies WHERE [Id] = @1 SET [Name] = @2;
Ответы
Ответ 1
Похоже, что SQL Server получит блокировки обновлений на любой записи, которую он должен прочитать , даже если он не изменит ее.
Дополнительная информация об этом поток microsoft.public.sqlserver.server:
Без индекса поддержки для CustomerContactPerson утверждение
УДАЛИТЬ ОТ ContactPerson ГДЕ ID = @ID;
Требуется "текущий" прочитайте все строки в CustomerContactPerson, чтобы убедиться, что не являются строками CustomerContactPerson, которые ссылаются на удаленные Строка ContactPerson. С помощью индекса DELETE может определить, что в CustomerContactPerson нет соответствующих строк, не читая строки, затронутые другой транзакцией.
Кроме того, в снимке транзакция - шаблон для чтения данных, которые вы собираетесь преобразовать вокруг и обновление - это делать UPDLOCK при чтении. Это обеспечивает что вы делаете свое обновление на основе "текущих" данных, а не "согласованные" (моментальные снимки) данные, а при выпуске DML это данные не будут заблокированы, и вы не будете перезаписывать другой смена сеанса.
Исправление для нас было добавление индексов к внешним ключам
В вашем примере, я подозреваю, что добавление индекса в Changes.CompanyId поможет. Я не уверен, что это настоящее решение. Может ли оптимизатор SQL Server не использовать индекс?
Ответ 2
SQL Server может видеть обновление зависимой таблицы, которая МОЖЕТ модифицировать поведение вставки... кажется мне справедливым, поскольку SQL не может угадать, какая другая логика может зависеть от столбца [name] (триггеры и т.д.),
если ваши приложения реализуют логику повтора логики блокировки, вы можете изменить их для обработки ошибки № 3960 так же, как ошибка № 1205 и автоматически повторить...