我正在从第三方提供的业务系统中提取数据以用于报告。我正在使用从 SSIS 数据流任务源组件发出的单个 SELECT 语句,该组件跨源系统中的多个表连接以创建我想要的数据集。我们使用默认的已提交读隔离级别。
令我惊讶的是,我经常发现这个提取查询陷入僵局并被选为受害者。我不认为读提交事务中的 SELECT 可以做到这一点,但根据这个 SO 答案是可能的:读提交的隔离级别是否会导致死锁(Sql Server)?
通过使用跟踪标志 1204 和 12222,我确定了冲突的语句,以及有问题的对象和索引。本质上,争用是针对其中一个表的主键中的数据页。我需要使用其键上的连接从该表中提取(因此我要取出 S 锁),冲突语句正在执行 INSERT 并请求索引数据页上的 IX 锁。
(旁注:上面的SO谈到了非聚集索引发生的这个问题,但这似乎发生在聚集PK中。至少,根据我对事件日志中死锁信息的解释和“关联对象 ID”属性。)
这是我的限制:
- 冲突语句位于第三方提供的加密存储过程中,作为现成软件的一部分。不可能获得或更改明文代码。
- 我不想使用脏读,因为我需要提取的数据来保持其完整性。
- 我不清楚重组我的提取查询如何或是否可以防止这种情况发生。锁在我最感兴趣的桌子的 PK 上,我看不到使用 PK 的任何替代方案。
- 我不介意我的提取查询是受害者,因为我更喜欢这样而不是中断源系统的操作使用。但是,这确实会导致 SSIS 执行失败,所以如果必须这样,我想要一种更干净、更优雅的方式来处理这种情况。
任何人都可以建议最好的方法来防止死锁,或者如果没有,那么更好地处理错误?