SQL Server 触发器插入导致锁定直到提交
Posted
技术标签:
【中文标题】SQL Server 触发器插入导致锁定直到提交【英文标题】:SQL Server trigger insert causes lock until commit 【发布时间】:2016-09-12 22:18:22 【问题描述】:在通过触发器锁定相关表时遇到问题。
我正在插入表tCatalog
(这有一个触发器可以简单地在另一个表tSearchQueue
中插入一条记录)。对tCatalog
的插入是在一个事务中,该事务具有许多其他功能,有时需要几秒钟。但是,tSearchQueue
表被锁定,直到可以提交事务。有没有办法避免这种情况?
INSERT INTO [dbo].[tSearchQueue] (Processed, SQL, sys_CreateDate)
SELECT
0, 'Test ' + cast(CatalogID as varchar(10)), getdate()
FROM
inserted
BEGIN TRAN t1
DECLARE @catalogid int
INSERT INTO tCatalog (ProgramID, sys_CreatedBy, ItemNumber, Description, UOMID)
VALUES (233, 1263, 'brian catalog4', 'brian catalog4', 416)
SELECT @catalogid = SCOPE_IDENTITY()
INSERT INTO tCustomAttributeCatalog (CatalogID, CustomAttributeID, DefaultValue, DefaultValueRead, sys_CreatedBy)
VALUES (@catalogid, 299, 'No', 'No', 1263)
INSERT INTO tCustomAttributeCatalog (CatalogID, CustomAttributeID, DefaultValue, DefaultValueRead, sys_CreatedBy)
VALUES (@catalogid, 300, null, null, 1263)
COMMIT TRAN t1
【问题讨论】:
为什么被tSearchQueue
锁定了?是什么导致了这种行为??你能避免这种情况吗?
@marc_s 这基本上就是我要问的问题。它似乎已被锁定,因为插入到 tCatalog 的事务尚未提交。我试图避免这种情况。
你能告诉我们插入TCatalog
吗?但是,仅此一项不应该锁定另一个表TSearchQueue
....
@marc_s 编辑问题以包含插入语句
谢谢 - 但再次:没有迹象表明对 TSearchQueue
表进行了任何操作.....不知道该表发生了什么,无法提供帮助,真的……
【参考方案1】:
看起来您有一个后台进程希望收到更改通知,以便它可以进行某种重新索引。如果是这种情况,它被阻塞不一定是错误,因为如果事务没有提交,那么它也不应该对其进行索引。
所以顺序是:
开始交易 插入 tCatalog 触发插入 tSearchQueue 插入一些其他表格 执行长时间运行的操作 提交事务。问题是另一个进程想要读取 tSearchQueue 但由于它被锁定而无法读取。
方案一:分批执行后台操作。
如果进程由于读取表格的机会太少而落后,那么一次读取多行可能会解决问题。 IE。每次它有机会读取队列时,它应该读取许多行,一次处理它们,然后将它们全部标记为一起完成(或视情况删除它们)。
选项 2:如果可能,首先执行长时间运行的操作:
开始交易 执行长时间运行的操作 插入 tCatalog 触发插入 tSearchQueue 插入一些其他表格 提交交易其他进程现在发现 tSearchQueue 只锁定了很短的时间。
请注意,如果长时间运行的操作是文件副本,则可以使用CopyFileTransacted
将这些包含在事务中,或者如果操作失败,可以在“catch”语句中回滚副本。
选项3:后台进程避免锁定
如果其他进程主要尝试读取表,那么快照隔离可能会解决您的问题。这将只返回已提交的行,因为它们在时间点存在。结合行级锁定,这可能会解决您的问题。
或者,后台进程可能会使用NOLOCK
提示进行读取(脏读取)。这可能会导致从稍后回滚的事务中读取数据。但是,如果在单独的步骤中验证数据(例如,您只是为需要重新索引的对象编写标识符),这不一定是问题。如果索引过程可以处理不再存在或实际上没有更改的条目,那么虚假读取就无关紧要了。
【讨论】:
以上是关于SQL Server 触发器插入导致锁定直到提交的主要内容,如果未能解决你的问题,请参考以下文章