트랜잭션으로 작업 그룹화

트랜잭션의 중요성

데이터베이스 시스템에서 트랜잭션은 데이터의 일관성과 무결성을 보장하는 핵심적인 개념입니다. 트랜잭션은 ‘All or Nothing’ 원칙을 따르며, 여러 작업을 하나의 논리적인 작업 단위로 묶어 처리합니다. 즉, 트랜잭션 내의 모든 작업이 성공적으로 완료되거나, 하나라도 실패하면 모든 변경 사항이 롤백되어 데이터베이스는 이전 상태로 유지됩니다.

트랜잭션 기본 속성 (ACID)

트랜잭션은 ACID 속성을 만족해야 합니다. ACID는 다음과 같습니다.

  • Atomicity (원자성): 트랜잭션은 분리될 수 없는 최소의 실행 단위입니다. 모든 작업이 완료되거나, 전혀 실행되지 않아야 합니다.
  • Consistency (일관성): 트랜잭션이 완료된 후 데이터베이스는 항상 일관된 상태를 유지해야 합니다.
  • Isolation (격리성): 동시에 실행되는 트랜잭션은 서로에게 영향을 미치지 않아야 합니다. 각 트랜잭션은 독립적으로 실행되는 것처럼 보여야 합니다.
  • Durability (지속성): 트랜잭션이 성공적으로 완료되면, 변경 사항은 영구적으로 데이터베이스에 저장되어야 합니다.

트랜잭션으로 작업 그룹화의 필요성

여러 SQL 문을 실행하여 하나의 논리적인 작업을 수행하는 경우, 이들을 트랜잭션으로 묶는 것이 중요합니다. 이렇게 하면 부분적인 실패로 인해 데이터가 불일치되는 상황을 방지할 수 있습니다.

예시: 은행 계좌 이체

두 개의 은행 계좌에서 돈을 이체하는 상황을 가정해 봅시다. 이 작업은 다음과 같은 두 단계로 구성됩니다.

  1. 계좌 A에서 금액 차감
  2. 계좌 B에 금액 추가

만약 첫 번째 단계는 성공했지만, 두 번째 단계에서 오류가 발생하면 계좌 A에서는 돈이 빠져나갔지만 계좌 B에는 돈이 들어오지 않는 문제가 발생합니다. 트랜잭션을 사용하면 이 문제를 해결할 수 있습니다.

PL/SQL 코드 예시

   
DECLARE
  v_account_a NUMBER := 100;
  v_account_b NUMBER := 200;
  v_amount NUMBER := 500;
BEGIN
  -- 계좌 A에서 금액 차감
  UPDATE accounts SET balance = balance - v_amount WHERE account_id = v_account_a;

  -- 계좌 B에 금액 추가
  UPDATE accounts SET balance = balance + v_amount WHERE account_id = v_account_b;

  COMMIT; -- 모든 변경 사항을 영구적으로 저장

EXCEPTION
  WHEN OTHERS THEN
   ROLLBACK; -- 오류 발생 시 모든 변경 사항 롤백
   RAISE; -- 예외 다시 발생
END;
/
  

위 코드에서 COMMIT은 트랜잭션의 모든 작업을 성공적으로 완료하고 데이터베이스에 변경 사항을 반영하는 명령어입니다. 반대로, ROLLBACK은 트랜잭션 도중 오류가 발생했을 때, 데이터베이스를 트랜잭션 시작 이전의 상태로 되돌리는 명령어입니다.

실행 결과

만약 코드가 성공적으로 실행되면 다음과 같은 메시지가 표시됩니다.

   
PL/SQL procedure successfully completed.
   
  

만약 오류가 발생하면, ROLLBACK 명령어가 실행되어 데이터는 이전 상태로 유지됩니다.

저장 시점을 이용한 보류 중인 트랜잭션 관리

복잡한 트랜잭션의 경우, 저장 시점(savepoint)을 사용하여 부분적인 롤백을 수행할 수 있습니다. 저장 시점은 트랜잭션 내의 특정 지점을 표시하며, 오류 발생 시 해당 지점 이후의 작업만 롤백할 수 있습니다.

PL/SQL 코드 예시

   
DECLARE
  v_account_a NUMBER := 100;
  v_account_b NUMBER := 200;
  v_amount NUMBER := 500;
BEGIN
  SAVEPOINT sp1;

  -- 계좌 A에서 금액 차감
  UPDATE accounts SET balance = balance - v_amount WHERE account_id = v_account_a;

  SAVEPOINT sp2;

  -- 계좌 B에 금액 추가
  UPDATE accounts SET balance = balance + v_amount WHERE account_id = v_account_b;

  COMMIT;

EXCEPTION
  WHEN OTHERS THEN
   ROLLBACK TO sp1; -- sp1 저장 시점 이후의 작업만 롤백
   RAISE;
END;
/
  

위 코드에서 SAVEPOINT 명령어는 저장 시점을 설정합니다. ROLLBACK TO sp1 명령어는 sp1 저장 시점 이후의 작업만 롤백하고, sp1 이전의 작업은 유지합니다.

제약 조건과 트리거의 역할

제약 조건(Constraints)과 트리거(Triggers)는 데이터 무결성을 유지하는 데 중요한 역할을 합니다. 제약 조건은 테이블에 저장되는 데이터에 대한 규칙을 정의하며, 트리거는 특정 이벤트(예: INSERT, UPDATE, DELETE)가 발생할 때 자동으로 실행되는 PL/SQL 코드 블록입니다.

제약 조건 예시

예를 들어, NOT NULL 제약 조건은 해당 열에 NULL 값이 저장되는 것을 방지하고, UNIQUE 제약 조건은 해당 열의 값이 테이블 내에서 유일해야 함을 보장합니다.

트리거 예시

트리거를 사용하여 계좌 이체 내역을 기록하거나, 특정 조건이 충족되었을 때 오류를 발생시킬 수 있습니다.

결론

트랜잭션은 데이터베이스 애플리케이션에서 데이터 무결성을 보장하는 데 필수적인 요소입니다. ACID 속성을 준수하고 저장 시점, 제약 조건, 트리거를 적절히 활용하면 데이터베이스의 신뢰성을 높일 수 있습니다. 개발자는 이러한 개념을 이해하고 적절하게 적용하여 데이터베이스의 안정성을 확보해야 합니다.

위로 스크롤