如何解决使用OPENJSON中的临时表在SELECT INTO上进行SQL Server自死锁
我们在开发中遇到了一个奇怪的问题,正在寻找有关临时表上带有SELECT INTO
的自锁问题的解释。
我们有一个例程,可以将一些相当复杂的JSON文档转换为表格形式。目前,我们正在使用OPEnjsON
来完成此操作,通常效果很好。
此转换发生在触发器的上下文中。当将一个或多个行插入表中时,将生成一组JSON文档,将其存储在单个变量中,并传递给以下例程。看起来像这样:
SELECT
a.[ID],b.[Some stuff here...]
INTO #MyTempTable
FROM OPEnjsON(@MyJSONDocuments)
WITH (
ID VARCHAR(40),nestedDocument NVARCHAR(MAX) AS JSON) a
CROSS APPLY OPEnjsON(nestedDocument,'$') b
当我们在SSMS中运行它时,它就可以正常工作。临时表已生成并填充,没有问题。当我们将其移至触发器并仅在基础表中插入一行(即@MyJSONDocuments
是单个文档的数组)时,它也可以正常工作。当我们插入两行或更多行,并且@MyJSONDocuments
在数组中包含多个文档时,我们会感到恐惧:
Transaction (Process ID x) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
当在SSMS中将SELECT INTO
语句包装到BEGIN TRAN / COMMIT TRAN
中时,也会遇到相同的死锁错误。
经过一些研究,我们发现问题可能是来自多个线程的并发问题,这些线程正在解析JSON并同时锁定temp表,从而导致死锁。当我们使用提示OPTION MAXDOP(1)
时,即强制查询是单线程的,没有死锁。同样,如果我们先创建临时表,然后再创建一个INSERT
,它也会起作用。
对于这个问题,我们有两个可行的解决方案,但是我仍然不清楚为什么这是一个问题。我想我的问题是:
1 / SELECT INTO
导致临时表上的自死锁的真正原因是什么?
2 /为什么错误仅在交易中发生?
3 /为什么死锁只发生在SELECT INTO
而不是常规INSERT
上?
谢谢大家!
编辑:下面的死锁图
解决方法
不确定该问题的完整答案,但我认为该问题与在事务上下文中并行访问OPENJSON结果有关。我遇到了完全相同的问题,可以通过设置OPTION(MAXDOP 1)在查询的那一部分上强制执行串行计划来解决。
尝试一下:
Object.create
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。