2014-09-03 1 views
6

나는 매주 "release"하는 데이터베이스를 가지고 있는데, 이는 사람들이 시작할 수있는 백업을 게시하고, 지난 주에 업그레이드 할 수있는 업데이트 스크립트를 게시 함 (가능한 한 최신 데이터를 유지할 수 있도록 함)). 물론이 스크립트에는 많은 DDL-CREATE TABLE, ALTER TABLE 등이 포함되어 있습니다. 그것의 기본 구조는 다음과 같다 :SQL Server의 CREATE TABLE 문은 ROLLBACK에 영향을받지 않습니까?

/* 

HOW TO USE THIS SCRIPT 

1. Run it against your existing DB 
2. Check whether there were any errors 
3. If there were, issue a rollback by highlighting this: 
     ROLLBACK 
    and executing it 
4. If there weren't, issue a commit by highlighting this: 
     COMMIT 
    and executing it 
5. !!! Not doing either of these will leave a transaction open, which will 
    probably cause all further queries to time out till you do !!! 

*/ 

SET XACT_ABORT ON; 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 

BEGIN TRANSACTION; 
GO 

-- Boilerplate checking and whatnot goes here 
GO 

-- Guts of operation, part 1 
GO 

-- Guts of operation, part 2 
GO 

-- Guts of operation, part 3 
GO 

-- . . . 
GO 

-- Guts of operation, part N 
GO 

-- Boilerplate cleanup stuff here 
GO 

당신은 내가 열린 트랜잭션을 떠나, 수동으로 마무리 무슨 일이 있었는지에 따라 처리하는 그들에게 있습니다 것입니다. 나는 이것을 자동으로 처리하고 싶지만 모든 것이 항상 여러 개의 일련의 긴 일련의 시리즈이며, TRY 개의 블록이 배치를 확장 할 수는 없다는 점에서 절망적이다. 따라서 최근에 추가 된 SET XACT_ABORT ON;은 약간의 고통을 완화합니다. 그럼에도 불구하고 나는 그것을 사용하지 않았기 때문에 나 자신을 시험해 보았고 시나리오에 아무런 차이가 없다. 어쨌든.

최근에 이러한 스크립트 중 하나에는 테이블 및 기타 명령문을 작성하여 기존 테이블에 점검 제한 조건을 추가하는 명령문이 있습니다. 내 사용자 중 한 명이 스크립트를 실행하고 제약 조건에 오류가 발생했습니다. 그가 제약 조건을 위반 한 기존 데이터를 가지고 있음이 밝혀졌습니다. 좋아, 문제 없으니 ROLLBACK. 그래, 하나 할 필요가 없었어요, XACT_ABORT 이미 그랬어. 가서 데이터 행을 수정하십시오 ... 완료되었습니다. 이제 다시 시도하십시오! 어 .. 뭐? 이번에는 제약 조건에 오류가 없지만 표가 이미 존재한다고 말하는 CREATE TABLE 문에서 오류가 발생했습니다 ...! 응? 롤백하지 않았 니?

우리는 백업에서 복원하고 데이터를 다시 고정하고 다시 실행합니다. 그러나 그것은 여기도 거기에 없습니다.

그럼 독자 들께 : 어떻게 트랜잭션 테이블을 만들었습니까? 어떻게하지 않을 수 있습니까?


편집 : 다음은 실행할 수있는 예입니다.

USE tempdb; 
GO 

CREATE DATABASE example; 
GO 

USE example; 
GO 

CREATE TABLE foo (a INT); 
GO 

INSERT INTO foo 
VALUES (100); 
GO 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 

BEGIN TRANSACTION; 
GO 

ALTER TABLE foo ADD CHECK (a < 10);-- Gives error "The ALTER TABLE statement conflicted with the CHECK constraint…", as expected 
GO 

CREATE TABLE bar (b INT); 
GO 

ROLLBACK;-- Gives error "The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION." Huh? Where did our transaction go? 
GO 

SELECT * 
FROM bar;-- Gives no error. Table still exists! NOT expected! 
GO 

USE tempdb; 
GO 

DROP DATABASE example; 
+0

아니요. 롤백에 영향을받지 않으므로 설명에서 자신의 경우에 일어난 일을 알기가 어렵습니다. –

+0

문제를 재현 할 수있는 가장 간단한 방법을 찾아보십시오. 그것은 우리가 문제를 분석하는 데 도움이 될 것입니다. – Andomar

답변

5

SQL Server에는 불행한 오류 처리 동작이 있습니다. 특정 오류에 따라 명령문, 일괄 처리, 트랜잭션 및 연결 또는 일부 또는 없음을 중단하는 경우가 있습니다. 이것은 프로그램하기에 매우 오류가 발생하기 쉬운 모델입니다.

XACT_ABORT으로 인해 일괄 처리 및 트랜잭션이 중단되었습니다. 그러나 GO은 배치 구분 기호입니다. 여러 개의 배치가 있습니다. 나중에 일괄 처리가 계속 실행됩니다.

일괄 처리를 사용하거나 나중에 일괄 처리가 실행되었는지 나중에 확인하십시오 (어쩌면 @@TRANCOUNT을 선택하여 확인).

(SQL Server의 더 좋은 모델은 트랜잭션을 롤백하지만 열려있는 상태로 유지하고 이후의 모든 명령문을 실패하게 만들면 나머지 스크립트는 트랜잭션에 포함되어 누출되지 않습니다. 이러한 기능이 있습니다.

+1

아, 그게 무슨 일이야! SQLcmd 모드와': on error exit'가 도움이 될 수 있습니다. –

+0

흠, 아직 존재하지 않는 개체에 대해 구문 검사를 통과하지 않기 때문에 단일 배치를 제거 할 수 없습니다. 예를 들어,'CREATE TABLE'과 결과 테이블에서 뭔가를하는 것과 같은 것 사이에서'GO '를해야합니다. 그렇지 않으면 실행을 시도하지 않습니다.그리고 나는 사용자들에게 SQLCmd 모드를 설명 할 희망이 거의 없다. :/ – Atario

+0

@Atario 잘 시도해 보면 모든 것을 감쌀 수 있고 catch 블록에서 오류를 잡아 내거나 'noexec on'을 설정한다. –