1

使用 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]

这个过程继续通过许多这样的表。如您所见,我没有在暂存表中的 SELECT 中包含 WHERE 子句,因为该表在流程结束时被截断。但是,这留下了另一个进程在此事务的中间向此临时表添加记录的可能性,并且这些记录将不包含先前填充的 FK。我是否要发布此声明以防止这种情况发生?:

 SET TRANSACTION ISOLATION LEVEL SNAPSHOT

如果这是最好的解决方案,那么这样做的缺点是什么?

4

2 回答 2

1

所有隔离级别,包括快照,只影响读取。stageTable 中的 SELECT 不会看到未提交的插入,也不会阻塞。我不确定这是否可以解决您将所有内容都放入 stageTable 而不考虑所有权的问题。当事务最终提交时会发生什么,stageTable 中的所有中间结果都准备好供下一个事务读取?也许您应该使用临时的#stageTable 来确保并发线程之间的自然隔离。

要了解使用快照隔离的成本,请阅读行版本控制资源使用情况

  • tempdb 中消耗的额外空间
  • 数据表中每一行消耗的额外空间
  • 大型字段在 BLOB 存储中消耗的额外空间
于 2010-01-05T18:01:13.353 回答
1

您是否可以在临时表中添加批次 ID,以便可以在 where 子句中使用它来确保您只处理原始批次的记录?将记录添加到临时表的任何进程都必须使用新的唯一批次 ID。我认为这将比依赖快照隔离更有效(也更健壮)。

于 2010-01-05T18:19:12.500 回答