我一直在我的实时应用程序中遇到死锁错误,并已将它们(使用 sql server profiler 的“死锁图”)跟踪到after insert
我的表上定义的触发器。
基本上情况是这样的——我想跟踪插入到某些表中的记录,按时间范围分组。(即在 12:00-12:10 之间,有 7 条记录被插入Users
)。
我实现它的方式是after insert
在这些表上创建触发器,因此当插入记录时,我会更新统计表中的相应记录。(见下文)。
正如我所说,这似乎造成了僵局。发生的事情是(我认为,我还没有找到确定的方法)是每个事务在提交之前可能会在多个表中插入/更新多个记录。
所以事务 1 出现,更新统计表中的某条记录(从而锁定它),然后继续更新表 B 中的记录。
同时,事务 2 将一条记录插入到表 B 中(从而锁定它),并尝试更新统计表中的记录 - 导致死锁。
(这当然是可能发生的事情的一个非常简化的版本。实际上我还不是 100% 确定)。
现在我最初的想法是看看是否有可能在 commit 之后执行触发器,以便事务不再持有任何锁。
但是,据我所知,没有这样的选择。
另一种解决方案是完全消除触发器,并改用某种批处理作业。
欢迎任何其他关于首选解决方案的想法/想法。
触发代码:
SELECT @TimeIn = I.TimeIn,
@TimeOut = I.[TimeOut],
FROM Inserted AS I
SET @NoOfPAX = 1
SET @Day = DATEADD(dd,0,DATEDIFF(dd,0,@TimeOut))
SET @HourOfTheDay = DATEPART (HOUR, @TimeOut)
SET @MinuteOfTheHour = DATEPART (MINUTE, @TimeOut)
SELECT @HourlyStatsExists = COUNT(*)
FROM dbo.DataWarehouse_HourlyStats
WHERE [Day] = @Day
AND HourOfTheDay = @HourOfTheDay
AND MinuteOfTheHour = @MinuteOfTheHour
IF @HourlyStatsExists = 0
BEGIN
INSERT INTO dbo.DataWarehouse_HourlyStats
(
HourOfTheDay,
MinuteOfTheHour,
[Day],
Total
)
VALUES (
@HourOfTheDay,
@MinuteOfTheHour,
@Day,
@NoOfPAX
)
END
ELSE
BEGIN
UPDATE DataWarehouse_HourlyStats
SET Total = Total + @NoOfPAX,
LastUpdate = GetDate()
WHERE [Day] = @Day
AND HourOfTheDay = @HourOfTheDay
AND MinuteOfTheHour = @MinuteOfTheHour
END