通过触发器锁定相关表格时遇到问题。
我正在插入表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
答案 0 :(得分:0)
看起来您有一个后台进程,希望收到更改通知,以便进行某种重新索引。如果情况不一定错误它被阻止,那么如果交易没有提交,那么它无论如何都不应该为它编制索引。
所以顺序是:
问题是另一个进程想要读取tSearchQueue但是因为它被锁定而不能。
选项1:批量执行后台操作。
如果进程落后,因为它几乎没有机会读取表,那么一次读取多行可以解决问题。即每当它有机会读取队列时,它应该读取许多行,一次处理它们,然后将它们全部标记为一起完成(或根据具体情况删除它们)。
选项2:如果可能,首先执行长时间运行操作:
其他进程现在发现tSearchQueue仅在短时间内被锁定。
请注意,如果长时间运行的操作是文件副本,则可以使用CopyFileTransacted
将这些操作包含在事务中,或者可以在" catch"中回滚这些副本。声明如果操作失败。
选项3:后台进程避免锁定
如果其他进程主要尝试读取表,则快照隔离可以解决您的问题。这将仅返回已提交的行,因为它们存在于该时间点。结合行级锁定可以解决您的问题。
或者,后台进程可能会读取NOLOCK
提示(脏读)。这可能导致从稍后回滚的事务中读取数据。但是,如果在单独的步骤中验证数据(例如,您只是编写需要重新索引的对象的标识符),则这不一定是个问题。如果索引过程可以处理不再存在的条目,或者实际上没有变化的条目,那么虚假读取就不重要了。