使用SQL2k5,我有一个临时表,其中包含将填充许多其他表的列。例如,这样的陈述:
INSERT INTO [appTable1] ([colA], [colB])
SELECT [appTable1_colA], [appTable1_colB]
FROM [stageTable]
然后[appTable1]上的触发器将新插入的行的标识列值填充回[stageTable];对于这个例子,我们会说它是[stageTable]。[appTable1_ID]然后作为FK插入到其他表中。更多类似的陈述如下:
INSERT INTO [appTable2] ([colA], [colB], [colC], [appTable1_FK])
SELECT [appTable2_colA], [appTable2_colB], [appTable2_colC], [appTable1_ID]
FROM [stageTable]
这个过程会继续通过这样的众多表格。正如您所看到的,我没有在登台表的SELECTs上包含WHERE子句,因为该表在进程结束时被截断。但是,这使得另一个进程可能会在此事务中间向此临时表添加记录,并且这些记录将不包含先前填充的FK。我是否想发布此声明以防止这种情况?:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
如果这是最佳解决方案,那么这样做的缺点是什么?
答案 0 :(得分:1)
所有隔离级别(包括快照)仅影响读取。 stageTable中的SELECT不会看到未插入的插入,也不会阻塞。我不确定这会解决你把所有东西扔进舞台表而不考虑所有权的问题。当事务最终提交时会发生什么,stageTable的所有中间结果都准备好被下一个事务读取?也许你应该使用一个临时的#stageTable来确保concurent线程之间的自然隔离。
要了解使用快照隔离的成本,请阅读Row Versioning Resource Usage:
答案 1 :(得分:1)
您是否可以在登台表中添加批次ID,以便可以在where子句中使用它,以确保您只处理原始批记录?将记录添加到登台表的任何进程都必须使用新的唯一批处理ID。我认为这比依赖快照隔离更有效(也更强大)。