트랜잭션 롤백시에도 SQL ID (자동 번호)가 증가합니다.


78

SQL Server 2005 데이터베이스에 대한 SQL 삽입이있는 .net 트랜잭션이 있습니다. 테이블에는 ID 기본 키가 있습니다.

트랜잭션 내에서 오류가 발생하면을 Rollback()호출합니다. 행 삽입은 올바르게 롤백되지만 다음에 테이블에 데이터를 삽입하면 롤백이 발생하지 않은 것처럼 ID가 증가합니다. 따라서 본질적으로 동일성 서열에는 간격이 있습니다. Rollback()메서드가 누락 된 ID를 회수하도록 하는 방법이 있습니까?

올바른 방법으로 접근하고 있지 않습니까?


Sugested edit : "autonumber"를 "identity"로 변경합니다. Autonumber는 MS Access 용어이고 Identity는 SQL Server에서 적절한 용어입니다.
Rick

아직 게시물을 답변으로 표시하지 않으 셨나요? 여전히 '당신의 대답'을 기다리고 있습니까?
Kangkan

2
가장 많이 득표 한 답변은이 행동을 피하는 질문에 실제로 답변하려고 시도하지 않습니다. 접근 방식이 올바른지 여부에 관계없이.
Jeff Swensen

답변:


105

생각해 보면 자동 증가 번호 트랜잭션 이 아니어야 합니다. 다른 트랜잭션이 자동 번호가 사용되는지 또는 "롤백"되는지 확인하기 위해 기다려야하는 경우 자동 번호를 사용하는 기존 트랜잭션에 의해 차단됩니다. 예를 들어, ID 열에 자동 번호 필드를 사용하는 테이블 A가있는 아래의 내 의사 코드를 고려해보십시오.

User 1
------------
begin transaction
insert into A ...
insert into B ...
update C ...
insert into D ...
commit


User 2
-----------
begin transaction
insert into A ...
insert into B ...
commit

사용자 2의 트랜잭션이 사용자 1의 1 밀리 초 후에 시작되면 테이블 A에 대한 삽입은 A에 대한 첫 번째 삽입의 자동 번호가 사용되었는지 확인하기 위해 사용자 1의 전체 트랜잭션이 완료 될 때까지 기다려야합니다.

이것은 버그가 아니라 기능입니다. 밀접하게 순차적이어야하는 경우 다른 체계를 사용하여 자동 번호를 생성하는 것이 좋습니다.


시퀀스 단단히 일련 번호를 생성하는 SQL 서버를 2012 힘 도움말을 시작하는 기능 - simple-talk.com/sql/learn-sql-server/sql-server-sequence-basics
통화 연결음

35

당신의 정체성 가치가 틈이 없다는 것에 의존한다면, 그렇습니다-당신은 그것을 잘못하고 있습니다. 대리 키의 요점은 비즈니스 의미없다는 것 입니다.

그리고이 동작을 변경할 수있는 방법이 없습니다 (자신의 자동 증분을 롤링하지 않고 다른 인서트를 차단하는 성능 결과를 겪음).


16

DELETE행인 경우 시퀀스에 간격이 생깁니다 .

시퀀스는 고유해야하지만 순차적 일 필요는 없습니다. 이들이 단조롭게 증가하고 있다는 사실은 구현의 우연에 불과합니다.


6

내가 아는 한 삽입 행이 자동 번호를 주장하고 롤백하면 해당 번호가 영원히 손실됩니다. 자동 번호가 시퀀싱에 의존하는 경우 사용중인 접근 방식을 고려할 수 있습니다.


6

걱정하지 말고 틈 이 있어야 한다고 말하는 다른 모든 포스터 가 맞습니다. 숫자에 비즈니스 의미가 있고 그 의미가 틈새에 맞지 않으면 ID 열을 사용하지 마십시오.

참고로, 어떤 이유로 든 간격을 제거하려는 경우 대부분의 데이터베이스에는 자동 번호 지정을 선택한 번호로 다시 시드하는 방법이 있습니다. 그것은 엉덩이에 고통스럽고 정기적으로해야 할 필요가 있다면 위에서 언급했듯이 자동 번호 / ID 필드를 사용하지 않아야합니다. 그러나 다음은 SQL 서버에서 수행하는 코드입니다.

DBCC CHECKIDENT ( '제품', RESEED, 0)

그러면 제품 테이블이 1부터 다시 시작하도록 설정됩니다 (테이블에 레코드가있는 경우 분명히 이미 사용 된 ID 값을 건너 뜁니다.) 다른 RDBMS 공급 업체에는 자체 구문이 있지만 효과는 거의 동일합니다. 시스템 도움말 파일이나 인터넷에서 "reseed identity"또는 "reseed autonumber"를 찾으십시오.

다시 말하지만 이것은 정기적 인 사용이 아닌 특별한 경우를위한 것입니다. 저장 프로 시저에 넣지 말고 우리 모두가 거기로 오게 만드십시오.


6
내 마음에 reseed는 라이브 데이터를 준비하기 위해 테스트 데이터를 제거 할 때만 사용해야합니다. 그리고 프로덕션 시스템에는 거의 없습니다.
HLGEM 2009

3
" 테이블에 레코드가있는 경우 이미 사용 된 ID 값을 건너 뛸 수 있습니다. "-내 경험에 따르면 그렇지 않은 경우 중복 된 기본 키 제약 조건 위반이 발생합니다. INSERT (SQL Server 2008에서 테스트 됨). 테이블의 최대 ID 값으로 다시 시드해야합니다. 다음 INSERT에서 다음 값 (예 : 사전 증가)을 할당합니다.
samgak

4

자동 번호 지정 키가 순차적이어야한다는 요구 사항이 없다고 생각합니다. 사실, 나는 그들이 다음과 같이 요구 될 수 있다고 생각하지 않습니다.

  • 트랜잭션 a 시작 및 삽입

  • 트랜잭션 b 시작 및 삽입

  • 트랜잭션 중단

    구멍이 생깁니다. 그것에 대해 할 일이 없습니다.


1

무한은 한 번에 하나씩이 아니라이 트랜잭션을 실행하는 많은 동시 연결의 맥락에서 생각하려고합니다. 일부는 실패하고 일부는 성공합니다. SQL Server가 새 요청이 들어 오면 실행하는 데 집중하고 공백이없는 ID 열을 유지하는 데 집중하기를 원합니다. IMO it (가치의 격차)은 확실히 시간을 할애 할 가치가없는 것입니다.


1

아니요. 시퀀스 구현은 자율 트랜잭션을 사용합니다. Oracle에서 자율 트랜잭션은 한때 dbms 내부에 있었지만 이제는 사용자가 사용할 수 있도록 노출됩니다 (그리고 종종 잘못 사용됨).

PRAGMA AUTONOMOUS_TRANSACTION;' 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.