Jon*_*Jon 5 sql-server json temp-tables sqlperformance database-deadlocks
我们在开发过程中遇到了一个奇怪的问题,正在寻找有关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
Run Code Online (Sandbox Code Playgroud)
当我们在 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.
Run Code Online (Sandbox Code Playgroud)
当我们将SELECT INTO语句包装在 SSMS 中的 aBEGIN TRAN / COMMIT TRAN中时,我们也会遇到相同的死锁错误。
经过一番研究,我们发现问题可能是多个线程同时解析 JSON 并锁定临时表的并发问题,从而导致死锁。当我们使用提示OPTION MAXDOP(1)即强制查询单线程时,就不会出现死锁。同样,如果我们先创建临时表,然后再创建一个INSERT也可以。
我们有两个可行的解决方案来解决这个问题,但我仍然不清楚为什么这是一个问题。我想我的问题是:
SELECT INTO1/导致临时表自死锁的真正原因是什么?
2/ 为什么错误只发生在事务上下文中?
3/ 为什么死锁只发生在 aSELECT INTO而不是常规的INSERT?
谢谢大家!
编辑:下面的死锁图
不确定这个问题的完整答案,但我相信这个问题与事务上下文中 OPENJSON 结果的并行访问有关。我有完全相同的问题,通过设置 OPTION (MAXDOP 1) 强制对查询的该部分执行串行计划来解决该问题。
尝试这个:
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
OPTION (MAXDOP 1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2473 次 |
| 最近记录: |