2011-04-18 2 views
3

나는이 대답에 약간의 설명을 좀하고 싶습니다 ->Nested stored procedures containing TRY CATCH ROLLBACK pattern?트랜잭션을 시작할 때만 SET XACT_ABORT를 호출해야합니까?

아래

1 CREATE PROCEDURE [Name] 
2 AS 
3 SET XACT_ABORT, NOCOUNT ON 
4 
5 DECLARE @starttrancount int 
6 
7 BEGIN TRY 
8 SELECT @starttrancount = @@TRANCOUNT 
9 
10 IF @starttrancount = 0 
11  BEGIN TRANSACTION 
12 
13  [...Perform work, call nested procedures...] 
14 
15 IF @starttrancount = 0 
16  COMMIT TRANSACTION 
17 END TRY 
19 BEGIN CATCH 
20 IF XACT_STATE() <> 0 AND @starttrancount = 0 
21  ROLLBACK TRANSACTION 
22 RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc] 
23 END CATCH 
24 GO 

는이 트랜잭션을 시작하는 기존 저장 프로 시저에서 호출 가정 위의 링크에서 코드 샘플입니다. 이 경우이 proc은 자체 트랜잭션을 시작하지 않고 호출에 대한 XACT_ABORT 상태를 변경합니다.

그래서 여기에 몇 가지 질문이 있습니다.

  • 는 XACT_ABORT 만 또는 전체 호출 스택의 현재 시저에 대한 작동 중입니까?
  • SET XACT_ABORT ON을 사용하는 proc을 리팩터링하려는 경우 을 SET XACT_ABORT OFF와 (과) 짝을 이루어야합니까? 레거시 코드 용으로 가장 안전한 방법입니까? 다음은

CREATE PROCEDURE [Name] 
AS 
SET NOCOUNT ON 

DECLARE @starttrancount int 

BEGIN TRY 
    SELECT @starttrancount = @@TRANCOUNT 

    IF @starttrancount = 0 
    BEGIN 
     SET XACT_ABORT ON 
     BEGIN TRANSACTION 
    END 

     [...Perform work, call nested procedures...] 

    IF @starttrancount = 0 
    BEGIN 
     COMMIT TRANSACTION 
     SET XACT_ABORT OFF 
    END 
END TRY 
BEGIN CATCH 
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
    BEGIN 
     ROLLBACK TRANSACTION 
     SET XACT_ABORT OFF 
    END 
    RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc] 
END CATCH 
GO 

답변

4

자식 배치 실행이 끝나면이 설정의 이전 값으로 복원됩니다. 당신이 올바른지 가정 ... 아직 모두 upvotes을 가지고, 확인하려면

SET NOCOUNT ON; 

BEGIN TRAN 

SELECT CASE 
     WHEN 16384 & @@OPTIONS = 16384 
      THEN 'XACT_ABORT IS ON' 
     ELSE ' XACT_ABORT IS OFF' 
     END 

CREATE TABLE #T 
    (
    C INT 
) 

SET XACT_ABORT OFF 

INSERT INTO #T 
VALUES  (1) 

EXEC ('SET XACT_ABORT ON; 
     INSERT INTO #T VALUES(2); 
     SELECT CASE 
        WHEN 16384 & @@OPTIONS = 16384 
        THEN ''XACT_ABORT IS ON'' 
        ELSE '' XACT_ABORT IS OFF'' 
       END 
     ') 


INSERT INTO #T 
VALUES  (1/0) 

/*If XACT_ABORT was on we would never get here but we do!*/ 
COMMIT 

SELECT * 
FROM #T 

DROP TABLE #T 

SELECT CASE 
     WHEN 16384 & @@OPTIONS = 16384 
      THEN 'XACT_ABORT IS ON' 
     ELSE ' XACT_ABORT IS OFF' 
     END 

반환

------------------ 
XACT_ABORT IS OFF 


------------------ 
XACT_ABORT IS ON 

Msg 8134, Level 16, State 1, Line 31 
Divide by zero error encountered. 
The statement has been terminated. 
C 
----------- 
1 
2 


------------------ 
XACT_ABORT IS OFF 
+0

, 이것은 아래의 대답은 (짐보의 대답은이 답변에 모순 즉, 내 독서에 관한 잘못된 의미 하는가 상당히 높은 평판을 얻으므로). – JohnLBevan

+1

@JohnLBevan - 예. –

0

이 XACT_ABORT 만, 또는 전체 호출 스택의 현재 시저에 대한 활성화 된 PROC 출구에 전원을 끈와 그것까지 조건부 XACT_ABORT와 쌍집니다 수정 된 샘플입니다 ? - 켜기로 설정하면 그 지점부터 그 모든 연결에 대해 활성화됩니다.

SET XACT_ABORT를 사용할 proc을 리팩토링하려면 SET XACT_ABORT를 OFF로 설정해야합니까?
- 원하는 동작 인 경우 예 - 그러면 기존 코드에서 새로운 동작을 얻지 못합니다.

레거시 코드를 사용하는 것이 가장 안전한 방법입니까? - 다른 저장 프로 시저에 미치는 영향을 최소화하려면 yes

관련 문제