防止在已提交读的SELECT

时间:2019-02-18 11:57:05

标签: sql-server tsql ssis deadlock read-committed

我正在从第三方提供的业务系统中提取数据以用于报告。我正在使用从SSIS数据流任务源组件发出的单个SELECT语句,该语句跨源系统中的多个表联接以创建所需的数据集。我们正在使用默认的已提交读隔离级别。

令我惊讶的是,我经常发现此提取查询陷入僵局并被选为受害者。我不认为在读提交的事务中执行SELECT可以做到这一点,但是根据这样的答案, 是可能的:Can a readcommitted isolation level ever result in a deadlock (Sql Server)?

通过使用跟踪标志1204和12222,我确定了冲突的语句以及相关的对象和索引。本质上,争用是在其中一个表的主键中的数据页上进行的。我需要使用其键上的联接从该表中提取(因此我要取出S锁),冲突的语句正在执行INSERT并正在索引数据页上请求IX锁。

(请注意:上面的SO谈论的是非集群索引出现的这个问题,但这似乎是在集群PK中发生的。至少,基于我的看法,解释事件日志中的死锁信息和“ associatedObjectId”属性。)

这是我的限制条件:

  1. 冲突的语句位于第三方提供的加密存储过程中,该软件作为现成软件的一部分。无法获取明文代码或对其进行更改。
  2. 我不想使用脏读,因为我需要提取的数据来保持其完整性。
  3. 我尚不清楚重组提取查询如何或是否可以阻止这种情况。锁位于我最感兴趣的表的PK上,我看不到使用PK的任何替代方法。
  4. 我不介意我的提取查询成为牺牲品,因为我宁愿这样,也不希望中断源系统的使用。但是,这确实会导致SSIS执行失败,因此,如果必须采用这种方式,我希望使用一种更简洁,更优美的方式来处理这种情况。

任何人都可以建议一些方法来最好地防止死锁,或者如果没有,则可以更好地处理错误?

1 个答案:

答案 0 :(得分:0)

我在这里的假设是,您试图将INSERT插入要选择的同一表中。如果否,则数据流选项卡的屏幕快照将有助于确定问题。如果是,那么您很幸运-我之前遇到过这个问题。

向数据流添加排序,因为这是完全阻塞的转换(有关阻塞转换,请参见下文)。这意味着在允许任何数据向下传递到目的地之前,将需要SELECT将所有数据完全加载到管道缓冲区中。否则,当表/索引上有锁时,SSIS尝试插入数据。您可能可以在这里通过索引策略发挥创意(我还没有尝试过)。但是,完全阻塞的转换将达到目的,并且消除了对该表添加任何其他索引的需求(以及随之而来的开销)。

注意:从表中选择数据时,从不不使用NOLOCK查询提示来解决此问题。我从来没有尝试过,也没有打算。您(贵族贵族)冒着将未提交的数据吸收到ETL中的风险。

参考:

https://jorgklein.com/2008/02/28/ssis-non-blocking-semi-blocking-and-fully-blocking-components/