2010-03-22 3 views
4

У меня есть база данных SQLServer 2008, в которой у меня есть таблица для тегов. Тег - это просто идентификатор и имя. Определение таблицы тегов выглядит так:Вопрос о параллельном тестировании SQL

CREATE TABLE [dbo].[Tag](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [varchar](255) NOT NULL 
CONSTRAINT [PK_Tag] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     IGNORE_DUP_KEY = OFF,  
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
) 

Название также является уникальным индексом. Далее у меня есть несколько процессов, добавляющих данные в эту таблицу довольно быстро. Эти процессы используют хранимую процедуру, которая выглядит как:

ALTER PROC [dbo].[lg_Tag_Insert] 
    @Name varchar(255) 
AS 


DECLARE @ID int 
SET @ID = (select ID from Tag where [email protected]) 

if @ID is null 
    begin 
      INSERT Tag(Name) 
      VALUES (@Name) 

      RETURN SCOPE_IDENTITY() 

    end 
else 
    begin 
     return @ID 
    end 

Моими вопросы, в том, что, кроме как новичок в параллельной разработке баз данных, кажется, есть состояние гонки, которая вызывает у меня иногда появляется сообщение об ошибке, что я Я пытаюсь ввести дубликаты ключей (Имя) в БД. Ошибка:

Невозможно вставить повторяющуюся строку ключа в объект 'dbo.Tag' с уникальным индексом 'IX_Tag_Name'.

Это имеет смысл, я просто не знаю, как это исправить. Если это где код, я бы знал, как заблокировать правильные области. SQLServer - совсем другой зверь.

Первый вопрос - это правильный способ кодирования этой «проверки, а затем обновления шаблона»? Кажется, мне нужно получить эксклюзивную блокировку строки во время проверки, а не общую блокировку, но мне не совсем понятно, как это сделать. Любая помощь в правильном направлении будет принята с благодарностью. Заранее спасибо.

ответ

0

Соответствующий код будет:

  • В SP, работает предпочтительно с сериализуемой сделкой
  • Сделать выбор в таблицу тегов первым, чтобы получить идентификатор
  • Если нуль, вставить.

Изоляция транзакций будет обеспечивать сериализацию транзакций.

Кэш-теги клиентской стороны, поэтому вы не вставляете, когда клиент уже знает, что они есть. Производительность будет минимальной.

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

Что вы можете сделать, это:

  • Используйте отдельные соединения для вставки тегов.
  • Когда вы получаете повторяющуюся ошибку, игнорируете ее, запрашиваете идентификатор, используйте id. Поскольку вы находитесь на отдельном соединении, это не имеет значения.
1

Я предпочитаю выходные параметры (так что я закодированы его таким образом), но это должно преформ быстро, с наименьшим количеством хитов на столе:

ALTER PROC [dbo].[lg_Tag_Insert] 
    @Name varchar(255) 
    ,@ID int OUTPUT 
AS 
BEGIN TRY 
    SET @ID=NULL 
    INSERT Tag (Name) VALUES (@Name) 
    SET @ID=SCOPE_IDENTITY() 
END TRY 
BEGIN CATCH 
    SELECT @ID=ID from Tag where [email protected] 
END CATCH 

IF @ID IS NULL 
BEGIN 
    RETURN 1 
END 

RETURN 0 

GO 
0

я нашел лучшие результаты в таблицах с тяжелыми вставки, чтобы установить ограничение на «Игнорировать дубликаты» и позволить обманутым падать на пол при захвате новых вставок. для вашего sproc вы можете полностью устранить тест и вернуть SCOPE_IDENTITY() или null после вставки.

Смежные вопросы