Взаимоблокировка MS-SQL при вставке в таблицу

#sql-server #python-3.x #multithreading #deadlock

#sql-сервер #python-3.x #многопоточность #взаимоблокировка

Вопрос:

Я использую следующий запрос для вставки в соответствующую историческую таблицу изменений, произошедших с данной таблицей. Я выполняю один и тот же запрос одновременно для нескольких таблиц в python (изменяя имя таблицы и базу данных). Ни одна из исторических таблиц не имеет внешних ключей. Но некоторые из казней заканчиваются тупиком. Каждой таблице должна быть присвоена уникальная историческая таблица. Я не уверен, как решить эту проблему. Это потому, что я использую таблицу переменных с одним и тем же именем во всех процедурах?

 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
введите описание изображения здесь

Комментарии:

1. Проверьте целевой файл трассировки system_health для получения сведений о событии взаимоблокировки .

2. Использование того же имени переменной не приведет к взаимоблокировке. Существуют ли какие-либо другие процессы, которые подключаются к этой БД во время вставки?

3. Одновременно существуют другие процессы, ссылающиеся на sys.all_columns в той же базе данных @PiotrS

4. Я использовал 10 потоков, поэтому у меня могло быть до 9 других процессов, обращающихся к БД во время выполнения вставки, для выполнения их собственной вставки в другие исторические таблицы

Ответ №1:

Похоже, что какой-то параллельный процесс одновременно изменяет или создает таблицу. Взаимоблокировка XML должна содержать дополнительные сведения о том, что происходит.

Но какой бы ни была фактическая причина, решение простое. Используйте приведенный выше сценарий для создания тел триггеров в статическом SQL, чтобы вам не приходилось запрашивать каталог для каждой вставки.

Создайте в своей базе данных процедуру, вызываемую, скажем, admin.GenerateHistoryTables и вызываемую admin.GenerateHistoryTriggers , и запустите их заранее, чтобы установить таблицы истории и подключить триггеры.

Или прекратите изобретать колесо и используйте сбор данных изменений или временные таблицы.