【发布时间】:2019-07-11 19:24:43
【问题描述】:
我正在从第三方提供的业务系统中提取数据以用于报告。我正在使用从连接源系统中的多个表的 SSIS 数据流任务源组件发出的单个 SELECT 语句来创建我想要的数据集。我们正在使用默认的已提交读隔离级别。
令我惊讶的是,我经常发现这个提取查询是死锁并被选为受害者。我不认为读取提交事务中的 SELECT 可以做到这一点,但根据这个 SO 回答它是可能的:Can a readcommitted isolation level ever result in a deadlock (Sql Server)?
通过使用跟踪标志 1204 和 12222,我确定了冲突的语句,以及有问题的对象和索引。本质上,争用是针对其中一个表的主键中的数据页。我需要使用其键上的连接从该表中提取(因此我要取出 S 锁),冲突语句正在执行 INSERT 并请求索引数据页上的 IX 锁。
(旁注:上面的 SO 讨论了 非聚集 索引发生的这个问题,但这似乎发生在聚集 PK 中。至少,这是我认为基于我的事件日志中的死锁信息和“关联ObjectId”属性的解释。)
这是我的限制:
- 冲突语句位于第三方提供的加密存储过程中,作为现成软件的一部分。无法获取或更改明文代码。
- 我不想使用脏读,因为我需要提取的数据来保持其完整性。
- 我不清楚重组我的提取查询如何或是否可以防止这种情况发生。锁在我最感兴趣的表的 PK 上,我看不到使用 PK 的任何替代方法。
- 我不介意我的提取查询成为受害者,因为我更喜欢这样做而不是中断源系统的操作使用。但是,这确实会导致 SSIS 执行失败,所以如果必须这样,我想要一种更干净、更优雅的方式来处理这种情况。
任何人都可以建议最好的方法来防止死锁,或者如果没有,那么更好地处理错误?
【问题讨论】:
-
考虑使用快照隔离事务来避免数据读取和死锁。
-
哪些特定的 SSIS 组件,即 OLE DB 源/目标、执行 SQL 任务等会导致死锁?
-
感谢@DanGuzman,阅读我认为它会起作用,尽管我认为它可能会影响业务系统对更改数据库设置的支持(即使设置快照隔离应该不影响现有查询)以及对 tempdb 大小的影响。
-
@userfl89 是的,它是 DFT 中的 OLE DB 源。死锁中涉及的另一个查询来自第三方应用程序,而不是来自 SSIS。
-
@GreatApe,是的,打开数据库
ALLOW_SNAPSHOT_ISOLATION会增加 tempdb 的使用率并产生每行 14 字节的额外开销。在许多情况下,收益大于开销。
标签: sql-server tsql ssis deadlock read-committed