SQL Server: состояние гонки на INSERT? - PullRequest
0 голосов
/ 18 октября 2019

Я поддерживаю устаревший код с устаревшей базой данных.

Учитывая эту таблицу базы данных

CREATE TABLE Transactions 
(
    id INT IDENTITY(1,1) NOT NULL,
    personId INT NOT NULL,
    visitNumber INT NOT NULL
)

, если я хочу, чтобы visitNumber был уникальным в пределах personId, вызывает ли следующая вставка условие гонки из-за вызова MAX?

insert into Transactions (personId, visitNumber)
values (1,
        (select isnull(max(visitNumber), 0) + 1
         from Transactions
         where personId = 1))

Возможно ли, что два запроса могут запускаться одновременно, оба вызывают MAX одновременно и получают одно и то же значение, а затем оба пытаются вставить одно и то же значение?

Я работаю с существующей базой данных и таблицей, которая работает в течение многих лет. Да, я знаю, что могу добавить уникальный индекс на personId + visitNumber. Нет, я не могу кардинально изменить дизайн таблицы.

Так, например, у меня может быть две записи с разными значениями personId и одинаковым значением visitNumber, но две записи с одинаковым значением personId могут 'у меня не может быть такого же visitNumber.

Я думаю, что это не будет иметь условия гонки:

BEGIN TRANSACTION

    DECLARE @nextId INT;

    SELECT @nextId = ISNULL(MAX(field1), 0) + 1
    FROM Transactions WITH (UPDLOCK, HOLDLOCK)
    WHERE personId = 1;

    INSERT INTO Transactions (personId, visitNumber) 
    VALUES (1, @nextId)

    COMMIT TRANSACTION
...