为什么我的SQL Server触发器从不同的事务中写入具有相同时间戳的两条记录?

问题描述 投票:1回答:1

我有一个带有整数Status列的SQL Server表。我的代码更新记录的Status,然后在几毫秒后再次将其更新为另一个值。

此表具有触发器,每次History值更改时,该触发器都会将记录插入到单独的Status表中。

History表具有以下列:

  1. Id uniqueidentifier:更新记录的PK值(注意:不是外键-我们不需要参照完整性)
  2. Status int:已更新记录的新状态值
  3. 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()写入由冒号分隔的该字段。这是我得到的:

History table

每次更新都是在同一个会话和一个单独的事务中执行的,这都是我所期望的,但是仍然无法解释为什么记录共享相同的时间戳。

c# sql-server database-trigger ormlite-servicestack
1个回答
0
投票

谢谢sticky bitlptr。似乎操作系统是罪魁祸首。

© www.soinside.com 2019 - 2024. All rights reserved.