插入 Table 时死锁 MS-SQL

Deadlock MS-SQL when Inserting Into a Table

我正在使用以下查询插入给定 table 的相应历史 table 更改。我同时对 python 中的多个 table 执行相同的查询(更改 table 名称和数据库)。 None 个历史 table 具有外键。但有些处决最终陷入僵局。每个 table 都分配了一个独特的历史 table。我不确定如何解决这个问题。是不是因为我在所有的程序中都使用了一个同名的变量table?

declare @name_tab table (name_column varchar(200),
                       dtype varchar(200))
declare @columns varchar(max)
declare @query varchar(max)
declare @database varchar(200)
declare @table_name varchar(200)
set @database = '%s' 
set @table_name = '%s'

insert into @name_tab
select c.name as name_column,
        t.name as dtype
from sys.all_columns c
INNER JOIN sys.types t
    ON t.system_type_id = c.system_type_id
where OBJECT_NAME(c.object_id) = @table_name

set @columns= stuff((select ','+name_column from @name_tab FOR XML PATH('')),1, 1, '') 

set @query= 'insert into ' +@database+'..'+'HISTORY_'+@table_name+' select super_q.* from' +
        '(select cast (GETDATE() as smalldatetime) as TIME_MODIFIED, new_info.* from '+
        '(SELECT ' + @columns + ' From '+@database+'..'+@table_name + 
        ' except ' +
        'SELECT ' + @columns + ' From '+@database+'..'+'HISTORY_'+@table_name + ') new_info) as super_q'

          execute(@query) 

我从 system_health 那里得到了这个样本

似乎某些并发进程正在同时更改或创建 table。死锁 XML 应该包含有关正在发生的事情的更多详细信息。

但无论实际原因是什么,解决方法都很简单。使用上面的脚本以静态方式生成触发器主体 SQL,这样您就不必为每个插入查询目录。

在您的数据库中创建一个名为 admin.GenerateHistoryTables 的过程和一个名为 admin.GenerateHistoryTriggers 和 运行 的过程 提前 安装历史 tables 并连接触发器。

或者停止重新发明轮子并使用Change Data Capture or Temporal Tables