2012-02-16 6 views
17

어떻게 트랜잭션을 사용하는지에 대한 많은 질문이 있습니다. 내가 알고 싶은 것은 언제일까요? 어떤 상황에서? 어떤 유형의 쿼리입니까? Try-Catch 블록으로 충분할 수 있습니까? 기타 ...SQL Server에서 트랜잭션을 사용하는 경우

~ 20 개의 테이블과 ~ 20 개의 저장 프로 시저로 데이터베이스를 설계했습니다. 현재 내 SP 중 누구도 트랜잭션을 사용하지 않지만 전체적으로 수많은 Try-Catch 블록이 있습니다. 그 이유는 트랜잭션에서 랩 할 때마다 SP가 작동을 멈추고 누락 된 데이터로 끝날 것이고 Trans를 사용한 것보다 나빠질 것이기 때문입니다. 그래서 다시

...
  1. 트랜잭션을 사용할 수있는 적절한 시간이

    ?
  2. 후속 질문으로, 내가 사용하는 경우, 내 SP를 유발하는 것보다 부패를 방지하기 위해 다른 SP가 동시에 같은 데이터에 액세스하는 것을 방지하는 방법으로 어떻게 사용할 수 있습니까? 전혀 작동하지 않겠습니까?

저는 여기에 제품 이름을 바꾸기 위해 쓴 작은 샘플 SP는 다음과 같습니다

CREATE PROCEDURE spRenameProduct 
    @pKey int = NULL, 
    @pName varchar(50) 
AS 
BEGIN 
    BEGIN TRY 
     IF LTRIM(RTRIM(@pName)) = '' SET @pName = NULL 
     IF NOT @pKey IS NULL AND NOT @pName IS NULL BEGIN 
      declare @pKeyExisting int = (select MIN(ID) from rProduct where Product like @pName and not ID = @pKey) 
      IF @pKeyExisting is null BEGIN 
       update rProduct set IsValid = 1, Product = @pName where ID = @pKey 
      END ELSE BEGIN 
       update Request set ProductID = @pKeyExisting where ProductID = @pKey 
       update StatusReport set ProductID = @pKeyExisting where ProductID = @pKey 
       delete from rProduct where ID = @pKey 
      END 
     END 
    END TRY BEGIN CATCH END CATCH 
END 

이제 어떻게 두 사람이 동일한 시간에이를 사용한다면? 나는 정말로 싶지도 않고, 나에게는 시간이있다 (불행하게도). 키스. 이 경우에 가장 좋습니다. :)

+0

격리 수준을 트랜잭션과 혼합합니다. 격리를 사용하면 해당 단일 명령문이 지속되는 동안 다른 업데이트를 잠글 수 있습니다. 업데이트가 필요하거나 전체적으로 실패 할 경우 트랜잭션으로 래핑합니다. 두 개의 업데이트와 하나의 삭제를 동기화 상태로 유지하려면 트랜잭션이 수행 할 수있는 작업입니다. – Paparazzi

+0

@ BalamBalam 즉, 트랜잭션에서 두 개의 업데이트와 하나의 삭제 만 래핑하는 것이 좋지만 항상 전체 SP를 래핑하는 것은별로 의미가 없습니까? 그럼에도 불구하고 때때로 개발자들이 실수를 저지르기 때문에 때때로 trans가 너무 복잡해서 작업하기가 힘듭니다. null 참조 또는 무언가와 같은 무해한 예외 때문에 응용 프로그램이 실패하는 것을 원하지는 않습니다. 지혜의 말은 없습니까? 아직도 이것에 새롭다 :) – Chiramisu

+0

나는 그것을 더 명확하게 말하는 방법을 모른다. 세트 전체가 실패하거나 성공할 필요가 있다면 트랜잭션으로 랩핑하십시오. 고전적인 예는 수표에서 예금 계좌로 돈을 이체하는 것입니다. 예금이 실패하면 인출이 실패하기를 원합니다. 개발자 실수로 인해 데이터가 동기화되지 않는 경우 트랜잭션을 사용하지 마십시오. – Paparazzi

답변

27

당신이 만들고있는 데이터베이스 작업 집합이 원자 일 필요가있을 때 트랜잭션을 사용합니다.

즉, 모두 성공해야합니다. 또는이 실패합니다. 그 사이에는 아무것도 없습니다.

데이터베이스를 항상 일관된 상태로 유지하기 위해 트랜잭션을 사용해야합니다.

일반적으로 사용하지 않는 좋은 이유가 없다면 (예를 들어 장시간 실행되는 프로세스) 사용하십시오. 자세한 내용은 this blog post을 참조하십시오.


Try/Catch 블록은 트랜잭션과 관련이 없습니다.이 블록은 예외 처리에 사용됩니다. 이 두 가지 개념은 서로 관련이 없으며 서로의 대체물이 아닙니다.

+1

+1 그리고 ** NO ** -'try ... catch' 블록은 ** 트랜잭션 **을위한 충분한 대체물이 아닙니다 .... –

+0

@marc_s - 물론입니다. 지금 그것에 관한 단락을 추가했습니다 ... – Oded

+0

@Oded 내가 얻고 싶은 것은 제가 트랜잭션을 사용하는 것을 고려할 때 저에게 팁을 줄 수있는 개발자로서 찾을 수있는 것들입니다. 예를 들어, "음, 거기에'update' 문이 있습니다. 아마 트랜잭션을 사용해야합니다." 또는 "그건 단지'선택 '일 뿐이므로 분명히 거래가 필요하지 않습니다." 어떻게'delete'에 대해? 기본적인 CRUD 작업 또는 트랜스가 필요하다는 것을 나타내는 다른 것들? – Chiramisu

0

일반적으로 트랜잭션을 사용하면 데이터베이스 작업을 원 자성으로 수행 할 수 있습니다. 혼동은 이것이 의미하는 바입니다. SELECT, UPDATE, DELETE 등의 특정 조작과 관련이 없습니다. 이는 데이터 자체의의 L 의미에 관한 것입니다. 작업의 관점에서 보았을 때 상향식에서부터 그룹으로는 원자 적이라고 말합니다. 그러나 추상적 인 관점에서 보았을 때, 위에서 아래로 볼 때, 우리는 정보의 보전을 말합니다.

두 개의 계정이 있고 두 계정 사이의 이전에 돈을 생성하거나 소멸시키지 않으려는 경우가 쉬운 예입니다. 그룹으로 생성되거나 파괴 될 필요가있는 데이터 그룹이있는 경우 더 복잡한 다른 예가 될 수 있습니다. 다시 말해, 부분적인 정보를 갖는 것이 이치에 맞지 않습니다. 나는 당신이 사용자를 가졌고 그들이 성 (first and last)을 가졌다 고 항상 보장하기를 원한다면 예가 될 것 같다. 부분적인 이름이 아닙니다.

이렇게 말하면 사람들은 "작업이 모두 성공하거나 실패 할 필요가 있습니다"와 같은 원자 적 의미를 표현하기 위해 어구와 규칙을 제안합니다. 또한 사람들은 SELECT가 거래를 필요로하지 않는 것과 같은 패턴을 알아 채는 경향이 있습니다.

관련 문제