효율적인 트랜잭션 코딩

트랜잭션을 되도록 짧게 유지하는 것이 중요합니다. 트랜잭션이 시작되면 DBMS(데이터베이스 관리 시스템)가 트랜잭션이 끝날 때까지 많은 리소스를 보유하여 트랜잭션의 ACID(원자성, 일관성, 격리성, 영속성) 속성을 보호합니다. 데이터가 수정되면 다른 트랜잭션이 읽을 수 없도록 수정된 행이 배타적 잠금으로 보호되어야 하며 트랜잭션이 커밋되거나 롤백될 때까지 배타적 잠금이 유지되어야 합니다. 트랜잭션 격리 수준 설정에 따라 SELECT 문에서 트랜잭션이 커밋 또는 롤백될 때까지 보유해야 하는 잠금을 획득할 수 있습니다. 특히 많은 사용자가 사용하는 시스템에서는 트랜잭션을 되도록 짧게 유지하여 동시 연결 간에 리소스에 대한 잠금 경쟁을 줄여야 합니다. 실행 시간이 긴 비효율적인 트랜잭션은 사용자 수가 적을 때는 별로 문제가 되지 않지만 사용자가 많을 때는 심각한 문제가 됩니다.

코딩 지침

효율적인 트랜잭션을 코딩하려면 다음 지침을 참조하십시오.

  • 트랜잭션 중 사용자로부터 입력을 요청하지 마십시오.

    트랜잭션이 시작되기 전에 사용자로부터 필요한 입력 내용을 모두 입력받아야 합니다. 트랜잭션 중 추가 사용자 입력이 필요하면 현재 트랜잭션을 롤백하고 사용자 입력이 제공된 후 트랜잭션을 다시 시작해야 합니다. 사용자가 즉시 응답하더라도 사람의 반응 속도는 컴퓨터 속도보다 매우 느립니다. 트랜잭션에 의해 보유된 모든 리소스는 꽤 긴 시간 동안 보유되므로 차단 문제가 발생할 수 있습니다. 사용자가 응답하지 않으면 응답할 때까지 몇 분 또는 몇 시간 동안 트랜잭션이 계속 활성 상태로 남아 있고 중요한 리소스가 잠겨 있게 됩니다.

  • 가능하면 데이터를 찾아보는 동안에는 트랜잭션을 열지 마십시오.

    모든 예비 데이터 분석이 완료될 때까지 트랜잭션을 시작하지 말아야 합니다.

  • 트랜잭션을 되도록 짧게 유지합니다.

    수정해야 한다고 판단되면 트랜잭션을 시작하고 수정 문을 실행한 다음 즉시 커밋 또는 롤백합니다. 필요할 때까지는 트랜잭션을 열지 마십시오.

  • 차단을 줄이려면 읽기 전용 쿼리에 행 버전 관리 기반의 격리 수준을 사용합니다. 자세한 내용은 행 버전 관리 기반 격리 수준 사용을 참조하십시오.

  • 낮은 트랜잭션 격리 수준을 효율적으로 사용하십시오.

    대부분의 응용 프로그램은 커밋된 읽기 트랜잭션 격리 수준을 사용하도록 코딩할 수 있습니다. 모든 트랜잭션에서 직렬화 가능 트랜잭션 격리 수준이 필요한 것은 아닙니다.

  • 낙관적 동시성 옵션과 같이 낮은 커서 동시성 옵션을 효율적으로 사용합니다.

    동시 업데이트 가능성이 적은 시스템에서는 한 사용자가 데이터를 읽은 후 다른 사용자가 해당 데이터를 변경하여 발생하는 오류를 처리하는 오버헤드가 데이터를 읽을 때마다 행을 잠그는 오버헤드보다 훨씬 적을 수 있습니다.

  • 트랜잭션에서는 가능한 적은 양의 데이터에 액세스합니다.

    이렇게 하면 잠긴 행 수가 줄어들어 트랜잭션 간의 경쟁이 감소됩니다.

동시성 문제 및 리소스 문제 방지

동시성 문제와 리소스 문제를 방지하려면 암시적 트랜잭션을 신중하게 관리합니다. 암시적 트랜잭션을 사용할 때는 COMMIT 또는 ROLLBACK 다음의 Transact-SQL 문이 자동으로 새 트랜잭션을 시작합니다. 이로 인해 응용 프로그램에서 데이터를 찾아보는 동안이나 사용자 입력이 필요할 때 새 트랜잭션이 열릴 수 있습니다. 데이터 수정을 보호하는 데 필요한 마지막 트랜잭션을 완료한 다음 데이터 수정을 보호하기 위해 트랜잭션이 다시 한 번 필요할 때까지 암시적 트랜잭션을 해제합니다. 이렇게 하면 응용 프로그램에서 데이터를 찾아보고 사용자로부터 입력을 받는 동안 SQL Server 데이터베이스 엔진이 자동 커밋 모드를 사용할 수 있습니다.

또한 스냅숏 격리 수준을 사용하면 새 트랜잭션이 잠금을 확보하지 않더라도 장기 실행 트랜잭션이 tempdb에서 이전 버전이 제거되지 않도록 방지합니다.