사용자 도구

사이트 도구


사이드바

tech:codeigniter:01.framework:트랜잭션_가이드

트랜잭션 가이드

개요

트랜잭션이란

  • 간단히 말해 여러 query의 수행결과(주로 insert, update, delete)를 하나의 그룹으로 묶어 동시에 반영(commit) 혹은 반영 취소(rollback)를 진행하기 위해 DB platform에서 제공하는 기술이다.
  • 사전적인 정의는 위키 참조

Kantukan ERP 에서의 트랜잭션

  • 칸투칸 ERP에서는 기본적으로 codeIgniter에서 제공하는 트랜잭션을 활용함
  • 그러나 보다 쉬운 활용 및 향후 공통 업데이트를 위해 KTK_model에 관련 트랜잭션 지원기능을 추가하여 해당 라이브러리 활용할 것을 권장

사용법

사용 범위

트랜잭션은 특성 상 Business layer (Model)에서만 활용 가능 (기술적으로는 다른 layer에서도 활용 가능하나 해당 프로젝트를 포함한 일반적인 프로젝트에서는 보통 금지합니다.)

자동 트랜잭션

자동 트랜잭션이란 commit, rollback 을 프레임웍에서 자동으로 결정하여 진행하는 트랜잭션 방식이다.

트랜잭션 시작

트랜잭션 시작 시 관련 datasource 이름을 지정할 수 있다 (미 지정시, default 활용)

트랜잭션 종료

트랜잭션 종료도 시작과 마찬가지로 datasource 이름 지정이 가능하며 미 지정시 역시 default 를 사용한다.

트랜잭션 결과 자동 판별 규칙

트랜잭션 시작과 종료 중의 쿼리 - 동일 datasource 를 활용하는 - 중에 오류가 없을 시 자동으로 commit이 진행된다.

예)

  • not null field에 null 값을 insert 혹은 update 시
    • 관련 쿼리 실패 및 같은 트랜잭션 구간 내의 모든 쿼리 롤백 진행
  • update 시 where 조건에 의해 업데이트 되는 row가 하나도 없을 시
    • 쿼리 자체는 성공하였기 때문에 트랜잭션 성공으로 간주 구간 내의 모든 쿼리가 commit 됨

소스 상에서의 트랜잭션 결과 확인 방법

트랜잭션 종료 시 return 값(true, false)을 통해 트랜잭션의 결과를 확인 할 수 있다.

사용 예제

/**
 * KTK_Model 을 extends한 model에서만 공용 트랜잭션 활용 가능
 * controller 등에서 트랜잭션 사용 금지
 */
class Prototype_model extends KTK_Model {
  /**
   * 트랜잭션 테스트 method
   */ 
  function transTest($paramArr=null) {
  /** 1. 트랜잭션 시작 선언 */
  $this->transStart();
    foreach ( $paramArr as $param) {
      $this->query("insertTestTable", array('param'=>$param)); // insert 쿼리 수행
    }
    // 업데이트의 경우는 대상 ROW 가 없어도 transaction 은 성공 (쿼리는 성공했기 때문)
    $this->query("updateTestTable");
 
    /** 2. 트랜잭션 종료 선언 (이 때 commit / rollback 이 이루어진다) */
    $result = $this->transEnd(); // $this->transComplete(); 로도 활용 가능하다
 
    /** 3. 결과 확인 및 분기처리 */
    if ( $result === true ) { /** 트랜잭션 성공 케이스 */ }
    else { /** 트랜잭션 실패 케이스 */ }
  }
}

수동 트랜잭션

수동 트랜잭션이란 commit, rollback 을 프레임웍이 아닌 개발자가 소스 상에서 직접 정의하여 결정하는 트랜잭션 방식이다.

사용 예제

/**
 * KTK_Model 을 extends한 model에서만 공용 트랜잭션 활용 가능
 * controller 등에서 트랜잭션 사용 금지
 */
class Prototype_model extends KTK_Model {
  /**
   * 매뉴얼 트랜잭션 테스트 method
   */ 
  function transTest($paramArr=null) {
  /** 1. 매뉴얼 트랜잭션 시작 선언 */
  $this->manualTransStart();
    foreach ( $paramArr as $param) {
      $this->query("insertTestTable", array('param'=>$param)); // insert 쿼리 수행
    }
    $this->query("updateTestTable");
 
    /** 2. 결과 확인 */
    $result = $this->getTransStatus(); // 해당 호출을 통해 자동 트랜잭션과 같은 조건 판단이 가능하다, 그러나 매뉴얼인 만큼 UPDATE ROW수 혹은 기타 조건을 통한 분기 처리가 가능하다.
 
    if ( $result === true ) { 
      /** 트랜잭션 성공 케이스 */
      // 앞의 null은 datasource name 이다, null일 경우 default
      $this->transEnd(null, true); // $this->transCommit(); 과 동일
 
    } else { 
      /** 트랜잭션 실패 케이스 */
      // 앞의 null은 datasource name 이다, null일 경우 default
      $this->transEnd(null, false); // $this->transRollback(); 과 동일
    }
  }
}

주의사항

트랜잭션의 유지 속성

  • 트랜잭션은 동일한 DB Pool에서만 작동이 됩니다.
  • CI환경에서는 $this→load→database(DB NAME, TRUE) 가 고유의 DB Pool을 얻는 행동이며, 동일한 DB NAME을 사용한다 하더라도 각각 해당 명령어를 통해 DB 객체를 얻었을 경우 서로 다른 DB Pool이 됩니다.
  • 본 프레임웍에서는 QueryParser 및 KTK_Model 의 지원으로 인해 $this→load→database 명령어를 사용할 필요가 없으며 하나의 Model내에서는 동일한 DB NAME일 경우 무조건 동일한 DB Pool로 관리되도록 설계되어 있습니다.
  • 즉 트랜잭션은 동일한 Model내에서는 유지가 될 수 있습니다. ($this→functionName(…) 방식으로 호출했을 경우)
  • 주의할 사항은 다른 Model을 객체로 호출하여 Function을 호출할 경우에는 서로 다른 Model이므로 transaction이 상호 유지되지 않습니다.
  • 또한, 동일 Model의 transaction 구간 내에서라도 DB NAME이 다를 경우 서로 다른 DB Pool이기에 transaction이 공유되지 않습니다.

여러 Model 에서 트랜잭션을 유지하는 방법

  • Model에서 Model을 호출하는 경우에는 아래와 같이 DB Pool을 동기화 할 수 있습니다.
 /**
  * DB Pool을 보유하고 있는 모델에서 신규 생성된 모델로 DB Pool 동기화
  * $this : DB Pool을 보유하고 있는 Model의 인스턴스
  * $insTargetModel :DB Pool을 받을 Model의 인스턴스
  */
$this->linkDBPoolTo($insTargetModel);
  • 주의사항
    • DB Pool을 받을 인스턴스의 기존 DB Pool은 삭제됩니다.
    • 두 개의 DB Pool이 동기화(by reference)되기 때문에 한 쪽에서 transaction commit 혹은 rollback을 하면 다른 model의 transaction 또한 영향을 받습니다.
    • 즉 한 모델에서 transaction을 시작했을 경우, 해당 명령어로 DB Pool이 연결된 모델에서는 transaction을 시작할 필요가 없습니다.
    • 해당 기능은 테스트가 필요합니다. 해당 기능으로 모델간 transaction을 유지하실 때에는 충분한 테스트를 부탁드리며, 문제가 발생하거나 의도대로 작동하지 않을 경우 문서 작성자에게 문의 부탁드립니다.

트랜잭션이 유지되지 않는 경우

  • Model에서 transaction start(혹은 begin) 을 하지 않은 경우
  • 서로 다른 DB Name 을 사용한 query 수행일 경우
  • Model 내에서 ($this 가 아닌) 다른 Model을 호출하여 DB Pool 연동 없이 query를 수행했을 경우
  • Controller 에서 model을 여러 번 호출하는 방식으로 복수의 query를 수행하는 경우 (Controller level에서 transaction을 묶을 수 없습니다.)
  • transaction 을 시작한 후 transEnd 혹은 commit을 명시적으로 선언하지 않았을 경우 (자동 rollback 됩니다.)
tech/codeigniter/01.framework/트랜잭션_가이드.txt · 마지막으로 수정됨: 2019/01/09 18:37 (바깥 편집)