防止读取提交的SELECT中出现死锁

问题描述 投票:0回答:1

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

令我惊讶的是,我经常发现这个提取查询是死锁并被选为受害者。我不认为读取提交事务中的SELECT可以做到这一点,但根据这个SO答案,它是可能的: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执行失败,所以如果必须这样,我想要一种更清晰,更优雅的方式来处理这种情况。

任何人都可以建议的方法,最好是防止死锁,或者如果没有,那么更好地处理错误?

sql-server tsql ssis deadlock read-committed
1个回答
0
投票

我在这里假设您正在尝试INSERT到您正在选择的同一个表中。如果不是,那么数据流选项卡的屏幕截图将有助于确定问题。如果是,那么你很幸运 - 我以前遇到过这个问题。

向数据流添加排序,因为这是一个完全阻塞的转换(请参阅下面有关阻止转换的信息)。这意味着在允许任何数据传递到目标之前,需要SELECT完成将所有数据加载到管道缓冲区中。否则,SSIS正在尝试在表/索引锁定时INSERT数据。您可以在此处获得有关索引策略的创意(我还没有尝试过)。但是,完全阻塞转换将完成这一操作,并且不需要对表的任何其他索引(以及需要的开销)。

注意:从表中选择数据时,永远不要使用NOLOCK查询提示作为尝试解决此问题。我从未尝试过这个,也不打算这样做。您(王室贵友)冒着将未提交的数据提取到您的ETL中的风险。

参考:

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

© www.soinside.com 2019 - 2024. All rights reserved.