У меня есть таблица [Файл], которая имеет следующую схему
CREATE TABLE [dbo].[File]
(
[FileID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](256) NOT NULL,
CONSTRAINT [PK_File] PRIMARY KEY CLUSTERED
(
[FileID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Идея состоит в том, что FileID используется в качестве ключа для таблицы, а Name - это полный путь к файлу.
То, что я пытался сделать, - это создать хранимую процедуру, которая проверит, если имя уже используется, если так, то используйте эту запись, иначе создайте новую запись.
Но когда я стресс-тестирую код с множеством потоков, одновременно выполняющих хранимую процедуру, я получаю разные ошибки.
Эта версия кода создаст взаимоблокировку и выдаст исключение взаимоблокировки на клиенте.
CREATE PROCEDURE [dbo].[File_Create]
@Name varchar(256)
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION xact_File_Create
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @FileID int
SELECT @FileID = [FileID] FROM [dbo].[File] WHERE [Name] = @Name
IF @@ROWCOUNT=0
BEGIN
INSERT INTO [dbo].[File]([Name])
VALUES (@Name)
SELECT @FileID = [FileID] FROM [dbo].[File] WHERE [Name] = @Name
END
SELECT * FROM [dbo].[File]
WHERE [FileID] = @FileID
COMMIT TRANSACTION xact_File_Create
GO
В этой версии кода я получаю строки с одинаковыми данными в столбце Имя.
CREATE PROCEDURE [dbo].[File_Create]
@Name varchar(256)
AS
BEGIN TRANSACTION xact_File_Create
SET NOCOUNT ON
DECLARE @FileID int
SELECT @FileID = [FileID] FROM [dbo].[File] WHERE [Name] = @Name
IF @@ROWCOUNT=0
BEGIN
INSERT INTO [dbo].[File]([Name])
VALUES (@Name)
SELECT @FileID = [FileID] FROM [dbo].[File] WHERE [Name] = @Name
END
SELECT * FROM [dbo].[File]
WHERE [FileID] = @FileID
COMMIT TRANSACTION xact_File_Create
GO
Мне интересно, как правильно делать этот тип действия? В целом, это шаблон, который я хотел бы использовать, когда данные столбца уникальны либо в одном столбце, либо в нескольких столбцах, а другой столбец используется в качестве ключа.
Спасибо