Функция SQL Server внутри оператора Select и взаимоблокировка транзакций

#sql #sql-server #stored-procedures #stored-functions #database-deadlocks

#sql #sql-сервер #хранимые процедуры #хранимые функции #база данных -взаимоблокировки

Вопрос:

С помощью кода, показанного ниже, я получаю взаимоблокировку транзакций. Split Функция принимает строку и разбивает список на таблицу, для которой я выполняю выбор. У меня есть событие READ UNCOMMITTED . Должен ли я поместить Split во временную таблицу, а затем выполнить с ней запрос?

 ALTER PROCEDURE [Revisions]
    @ScheduleRevisionIds NVARCHAR(MAX) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    IF(@ScheduleRevisionIds IS NOT NULL)
    BEGIN
        -- GET SCHEDULE REVISIONS
        SELECT esr.Id 
        INTO #TempScheduleRevisions
        FROM Revision esr
        WHERE EXISTS (SELECT items 
                      FROM dbo.Split(@ScheduleRevisionIds, ',') 
                      WHERE esr.Id = items) 
 

Функция

 ALTER FUNCTION [Split](@String varchar(MAX), @Delimiter char(1))       
returns @temptable TABLE (items varchar(MAX))       
as       
begin       
    declare @idx int       
    declare @slice varchar(MAX)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        SET @String = right(@String, LEN(@String) - @idx)       
        IF LEN(@String) = 0 BREAK       
    END   
RETURN       
END
 

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

1. Можете ли вы показать код split() функции?

2. Предполагая, что у вас есть разумно написанная функция разделения, я не понимаю, как может возникнуть взаимоблокировка в небольшом фрагменте опубликованного кода. Вам нужно будет глубже вникнуть в код, выполняемый соединениями, конкурирующими за доступ к ресурсам. По крайней мере, вам нужно определить ресурсы, находящиеся в конфликте.

3. (1) Какую версию SQL Server вы используете? С 2016 года вы можете использовать встроенную функцию STRING_SPLIT . (2) Зачем вам нужна эта функция разделения? Вы разбиваете строку на «,», чтобы просмотреть результат и проверить, существует ли определенный текст… почему бы просто не проверить, существует ли текст в исходной строке? Добавьте «,» в начало строки и проверьте, есть ли («,» esr.Id «,») существует в строке («,» @ScheduleRevisionIds «,»), используя что-то вроде where CHARINDEX("," esr.Id ",", "," @ScheduleRevisionIds ",") > 0

4. Если вы сможете опубликовать таблицу DD DML ожидаемый результат, мы, вероятно, сможем быстро предоставить полное решение / демонстрацию

5. Здесь недостаточно информации, чтобы сказать, поскольку должно быть что-то еще, вызывающее взаимоблокировку. Одна вещь, которую я обнаружил, — это то, что Select INTO может вызвать блокировку, в то время как CREATE TABLE, за которым следует INSERT, этого не делает. Вы можете попробовать это.

Ответ №1:

У меня нет ничего конкретного, чтобы сказать, что какая-либо часть вашего запроса приведет к взаимоблокировке транзакций. Но, я думаю, вы можете использовать объединения, которые, на мой взгляд, проще и могут вывести вас из неприятных тупиков. Итак, попробуйте это:

  SELECT esr.Id INTO #TempScheduleRevisions
 FROM 
 Revision esr
 INNER JOIN
 dbo.Split(@ScheduleRevisionIds, ',') sri
 ON
 sri.items = esr.id