我有一个带有整数Status
列的SQL Server表。我的代码更新记录的Status
,然后在几毫秒后再次将其更新为另一个值。
此表具有触发器,每次History
值更改时,该触发器都会将记录插入到单独的Status
表中。
History
表具有以下列:
Id uniqueidentifier
:更新记录的PK值(注意:不是外键-我们不需要参照完整性)Status int
:已更新记录的新状态值TimeUtc DateTime2(7)
:更新发生的时间一个NLog日志文件向我们显示,我们在关闭但时间不同的两个不同的数据库UPDATE
中进行了调用。但是,当我们随后在数据库中查找时,两个历史记录的TimeUtc
值与微秒相同:
Id: CD83... Status: 4 TimeUtc: 2020-3-20 16:14:26.6952631
Id: CD83... Status: 5 TimeUtc: 2020-3-20 16:14:26.6952631
为什么会这样?为了使这一点变得更加奇怪,有时,当我们运行并发代码时,几乎在同一时间将更新两个单独的记录,并且所有四个历史记录将具有相同的时间戳。
Id: CD83... Status: 4 TimeUtc: 2020-3-20 16:14:26.6952631
Id: CD83... Status: 5 TimeUtc: 2020-3-20 16:14:26.6952631
Id: 06EA... Status: 4 TimeUtc: 2020-3-20 16:14:26.6952631
Id: 06EA... Status: 5 TimeUtc: 2020-3-20 16:14:26.6952631
我们正在使用ServiceStack OrmLite更新值,并且文档告诉我,每个调用是一个单独的事务,(我认为)这将产生两个单独的触发事件,但这也许是错误的。看起来SQL Server正在保存触发事件并立即触发所有事件。 ServiceStack OrmLite可以在后台将调用批量处理为单个事务吗?
这里是触发器定义。让我知道是否需要更多详细信息:
CREATE TRIGGER [dbo].[ChangeStatus]
ON [dbo].[TableWithStatus]
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
-- On insert, or on update where status changed
INSERT INTO History
SELECT i.[Id], i.[Status], SYSUTCDATETIME()
FROM Inserted i
LEFT JOIN Deleted d ON i.Id = d.Id
WHERE i.[Status] IS NOT NULL
AND (d.[Status] IS NULL OR i.[Status] <> d.[Status])
END
GO
附录:我用第四个字段(varchar)更新了History表,并更新了触发器,以将@@ SPID和CURRENT_TRANSACTION_ID()写入由冒号分隔的该字段。这是我得到的:
每次更新都是在同一个会话和一个单独的事务中执行的,这都是我所期望的,但是仍然无法解释为什么记录共享相同的时间戳。
谢谢sticky bit和lptr。似乎操作系统是罪魁祸首。