При написании некоторых SQL запросов обновления сервера для взаимодействия с базой данных продукта я столкнулся с ситуацией, когда все в порядке, если две транзакции с этими обновлениями выполняются одновременно, но когда более двух транзакций пытаются обновить одна и та же таблица одновременно, некоторые из них оказались в тупике.
Я разбил проблему на ограничение «UNIQUE NONCLUSTERED» для определения таблицы. Когда я сниму это ограничение, все транзакции будут ждать своих необходимых ресурсов и завершатся sh без ошибок.
Вот мой пример кода для воспроизведения проблемы:
CREATE TABLE [dbo].[profiles]
(
[ProfileID] [int] IDENTITY(1,1) NOT NULL,
[ProfileName] [nvarchar](255) NOT NULL,
[GroupFK] [int] NULL
CONSTRAINT [PK_Profile]
PRIMARY KEY CLUSTERED ([ProfileID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY],
-- !!! [UI_UniqueNameInGroup] seems problematic for me because i get deadlocks when executing more than two transactions at once !!!
CONSTRAINT [UI_UniqueNameInGroup]
UNIQUE NONCLUSTERED ([GroupFK] ASC, [ProfileName] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO profiles (ProfileName) VALUES ('PROFILE_99')
INSERT INTO profiles (ProfileName) VALUES ('PROFILE_88')
INSERT INTO profiles (ProfileName) VALUES ('PROFILE_77')
INSERT INTO profiles (ProfileName) VALUES ('PROFILE_66')
Это образцы моих транзакций:
BEGIN TRAN
UPDATE profiles
SET ProfileName = 'NewProfile_99'
WHERE ProfileID = 4
WAITFOR DELAY '00:00:05.000'
COMMIT TRAN
BEGIN TRAN
UPDATE profiles
SET ProfileName = 'NewProfile_66'
WHERE ProfileID = 1
WAITFOR DELAY '00:00:05.000'
COMMIT TRAN
BEGIN TRAN
UPDATE profiles
SET ProfileName = 'NewProfile_88'
WHERE ProfileID = 3
WAITFOR DELAY '00:00:05.000'
COMMIT TRAN
BEGIN TRAN
UPDATE profiles
SET ProfileName = 'NewProfile_77'
WHERE ProfileID = 2
WAITFOR DELAY '00:00:05.000'
COMMIT TRAN
Вот мои графики взаимоблокировок:
deadlockgraph1.xdl
deadlockgraph2.xdl
Пожалуйста, помогите мне, объяснив мне проблему - я не понимаю, почему взаимоблокировки возникают только при одновременном выполнении более двух транзакций.
Мне также нравится просто получить для этого рабочее решение.
Есть ли решение на моей стороне (без изменения схемы базы данных)?