【问题标题】:SQL Server trigger insert causes lock until commitSQL Server 触发器插入导致锁定直到提交
【发布时间】:2023-03-29 11:11:01
【问题描述】:

在通过触发器锁定相关表时遇到问题。

我正在插入表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 表进行了任何操作.....不知道该表发生了什么,无法提供帮助,真的……

标签: sql sql-server triggers transactions deadlock


【解决方案1】:

看起来您有一个后台进程希望收到更改通知,以便它可以进行某种重新索引。如果是这种情况,它被阻塞不一定是错误,因为如果事务没有提交,那么它也不应该对其进行索引。

所以顺序是:

  • 开始交易
  • 插入 tCatalog
    • 触发插入 tSearchQueue
  • 插入一些其他表格
  • 执行长时间运行的操作
  • 提交事务。

问题是另一个进程想要读取 tSearchQueue 但由于它被锁定而无法读取。

方案一:分批执行后台操作。

如果进程由于读取表格的机会太少而落后,那么一次读取多行可能会解决问题。 IE。每次它有机会读取队列时,它应该读取许多行,一次处理它们,然后将它们全部标记为一起完成(或视情况删除它们)。

选项 2:如果可能,首先执行长时间运行的操作:

  • 开始交易
  • 执行长时间运行的操作
  • 插入 tCatalog
    • 触发插入 tSearchQueue
  • 插入一些其他表格
  • 提交交易

其他进程现在发现 tSearchQueue 只锁定了很短的时间。 请注意,如果长时间运行的操作是文件副本,则可以使用CopyFileTransacted 将这些包含在事务中,或者如果操作失败,可以在“catch”语句中回滚副本。

选项3:后台进程避免锁定

如果其他进程主要尝试读取表,那么快照隔离可能会解决您的问题。这将只返回已提交的行,因为它们在时间点存在。结合行级锁定,这可能会解决您的问题。

或者,后台进程可能会使用NOLOCK 提示进行读取(脏读取)。这可能会导致从稍后回滚的事务中读取数据。但是,如果在单独的步骤中验证数据(例如,您只是为需要重新索引的对象编写标识符),这不一定是问题。如果索引过程可以处理不再存在或实际上没有更改的条目,那么虚假读取就无关紧要了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多