0

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

令我惊讶的是,我经常发现这个提取查询陷入僵局并被选为受害者。我不认为读提交事务中的 SELECT 可以做到这一点,但根据这个 SO 答案可能的:读提交的隔离级别是否会导致死锁(Sql Server)?

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

(旁注:上面的SO谈到了非聚集索引发生的这个问题,但这似乎发生在聚集PK中。至少,根据我对事件日志中死锁信息的解释和“关联对象 ID”属性。)

这是我的限制:

  1. 冲突语句位于第三方提供的加密存储过程中,作为现成软件的一部分。不可能获得或更改明文代码。
  2. 我不想使用脏读,因为我需要提取的数据来保持其完整性。
  3. 我不清楚重组我的提取查询如何或是否可以防止这种情况发生。锁在我最感兴趣的桌子的 PK 上,我看不到使用 PK 的任何替代方案。
  4. 我不介意我的提取查询是受害者,因为我更喜欢这样而不是中断源系统的操作使用。但是,这确实会导致 SSIS 执行失败,所以如果必须这样,我想要一种更干净、更优雅的方式来处理这种情况。

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

4

1 回答 1

0

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

为数据流添加一个排序,因为这是一个完全阻塞的转换(参见下面的阻塞转换)。这意味着在允许任何数据向下传递到目的地之前,将需要 SELECT 完成将所有数据加载到管道缓冲区中。否则,当表/索引上存在锁定时,SSIS 会尝试插入数据。您也许可以在此处通过索引策略获得创意(我没有尝试过)。但是,完全阻塞的转换可以解决问题,并消除对表的任何额外索引的需要(以及由此产生的开销)。

注意:从表中选择数据时,切勿使用 NOLOCK 查询提示来解决此问题。我从未尝试过,也不打算这样做。您(皇室成员)冒着将未提交的数据摄入 ETL 的风险。

参考:

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

于 2019-02-18T19:35:28.780 回答