IDENTITY_INSERT는 동시성에 어떤 영향을 줍니까?


11

게시 결함이 있고 지원이 중단 된 타사 SAP 애드온으로 고객을 지원하려고합니다.

특정 상황에서는 게시 대기열 테이블에서 게시 보관 테이블로 게시 및 불완전한 게시물이 보관됩니다. 보관 된 결과를 다시 대기열로 이동해야합니다.

대기열 ID는 ID 열이며 동일하게 유지하고 싶습니다.

문제는 identity_insert on / insert / identity_insert off를 수행하면 대기열 항목을 생성하고 ID 열이 자동으로 생성되는 프로세스와의 동시성에 대해 무엇을 기대할 수 있습니까?

그러한 행동을 보여주는 가장 좋은 방법에 대한 조언도 대단히 감사하겠습니다.

답변:


8

설정 IDENTITY_INSERT ON자체에 동시성을 제거하지 않습니다 -이 테이블 만 간단한 스키마 안정성 (SCH-S) 잠금을 배타적 잠금을하지 않습니다.

이론적으로 기본 동작에서 발생할 수있는 일은 세션 1에서 수행 할 수 있다는 것입니다.

BEGIN TRANSACTION;

-- 1
SET IDENTITY_INSERT dbo.tablename ON;

-- 2
INSERT dbo.tablename(id, etc) VALUES(100, 'foo'); -- next identity is now 101

-- 3
INSERT dbo.tablename(id, etc) VALUES(101, 'foo'); -- next identity is now 102

-- 4
SET IDENTITY_INSERT dbo.tablename OFF;

COMMIT TRANSACTION;

다른 세션에서는 포인트 1, 2, 3 또는 4에서 테이블에 행을 삽입 할 수 있습니다. 2와 3 사이에서 발생하는 삽입에 대해 발생하는 것을 제외하고는 좋은 일처럼 보일 수 있습니다 . 자동 생성 된 값이 트리거 된 것입니다. 다른 세션에서는 명령문 2의 결과를 기반으로하므로 101을 생성 한 다음 기본 키 위반으로 명령문 3이 실패합니다. 이것은 약간 WAITFOR의 설정으로 자신을 설정하고 테스트하는 것이 매우 간단합니다 .

-- session 1
-- DROP TABLE dbo.what;
CREATE TABLE dbo.what(id INT IDENTITY PRIMARY KEY);
GO
BEGIN TRANSACTION;

SET IDENTITY_INSERT dbo.what ON;

INSERT dbo.what(id) VALUES(32);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(33);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(34);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(35);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(36);

SET IDENTITY_INSERT dbo.what OFF;

COMMIT TRANSACTION;

해당 배치가 시작되면 다른 창에서이 배치를 시작하십시오.

-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20

세션 2는 1-20 사이의 값만 삽입해야합니다. 수동 삽입 세션 1에서 기본 ID가 업데이트 되었기 때문에 어느 시점에서 세션 2는 세션 1이 중단 된 위치를 선택하고 32, 33 또는 34 등을 삽입합니다. 그러나이 작업은 허용됩니다. PK 위반으로 다음 삽입에서 세션 1이 실패합니다 (이기는 시간 문제 일 수 있음).

이 문제를 해결하는 한 가지 방법 TABLOCK은 첫 번째 삽입에서 를 호출하는 것 입니다.

INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);

이렇게하면 아카이브 된 행을 다시 이동할 때까지이 테이블에 삽입하거나 실제로 수행하려는 다른 사용자를 차단합니다. 이 조절판 동시성은, 물론,하지만 당신이 방법은 원하는 작업에 차단. 그리고 이것이 여러분이 다른 사람들을 항상 차단하는 빈번한 속도로 일어나지 않는 것이기를 바랍니다.

몇 가지 다른 해결 방법 :

  • IDENTITY생성 된 가치 에 대한 관심을 멈추십시오 . 무슨 상관이야? 원래 값이 매우 중요한 경우 (대리자로 UNIQUEIDENTIFIER별도의 테이블에서 생성 될 수 있음)을 사용하십시오 IDENTITY.
  • "초기 삭제"를 사용하도록 아카이브 프로세스를 변경하십시오. 여기서 무언가가 처음에 아카이브 된 것으로 표시되고 나중에 아카이브가 영구적으로 만들어지지 않습니다. 그런 다음 프로세스를 뒤로 이동하려고하면 직접 업데이트를 수행하고 소프트 삭제 플래그를 수정할 수 있습니다.

설명해 주셔서 감사합니다. 이러한 ID 필드를 만드는 지원되지 않는 제품을 지원하기 위해 독립형 유틸리티를 작성 중입니다. 작동 방식을 제어 할 수 없습니다.
은유
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.