PDO 트랜잭션 및 자동 커밋

이제 PDO를 통해 연결되었으므로 쿼리 실행을 시작하기 전에 PDO가 트랜잭션을 관리하는 방법을 이해해야 합니다. 이전에 트랜잭션을 본 적이 없다면 원자성, 일관성, 격리 및 내구성(ACID)의 4가지 주요 기능을 제공합니다. 평신도의 관점에서, 트랜잭션에서 수행되는 모든 작업은 단계적으로 수행되더라도 커밋될 때 다른 연결의 간섭 없이 안전하게 데이터베이스에 적용된다는 것이 보장됩니다. 트랜잭션 작업은 요청 시 자동으로 취소할 수도 있습니다(아직 커밋하지 않은 경우). 그러면 스크립트에서 오류 처리가 더 쉬워집니다.

트랜잭션은 일반적으로 일괄 변경 사항을 "저장"하여 한 번에 모두 적용함으로써 구현됩니다. 이것은 해당 업데이트의 효율성을 크게 향상시키는 좋은 부작용이 있습니다. 다시 말해, 트랜잭션은 스크립트를 더 빠르고 잠재적으로 더 강력하게 만들 수 있습니다(그 이점을 얻으려면 여전히 스크립트를 올바르게 사용해야 함).

불행히도 모든 데이터베이스가 트랜잭션을 지원하는 것은 아니므로 PDO는 처음 연결을 열 때 "자동 커밋" 모드에서 실행해야 합니다. 자동 커밋 모드는 데이터베이스가 지원하는 경우 실행하는 모든 쿼리에 자체 암시적 트랜잭션이 있고 데이터베이스가 트랜잭션을 지원하지 않는 경우 트랜잭션이 없음을 의미합니다. 트랜잭션이 필요한 경우 PDO::beginTransaction() 메서드를 사용하여 트랜잭션을 시작해야 합니다. 기본 드라이버가 트랜잭션을 지원하지 않으면 PDOException이 발생합니다(오류 처리 설정에 관계없이: 이것은 항상 심각한 오류 조건입니다). 트랜잭션에 참여하면 트랜잭션 중에 실행한 코드의 성공 여부에 따라 PDO::commit() 또는 PDO::rollBack()을 사용하여 완료할 수 있습니다.


경고 PDO는 드라이버 수준의 트랜잭션 기능만 확인합니다. 특정 런타임 조건에서 트랜잭션을 사용할 수 없는 경우 데이터베이스 서버가 트랜잭션 시작 요청을 수락하면 PDO::beginTransaction()이 여전히 오류 없이 true를 반환합니다.

이에 대한 예는 MySQL 데이터베이스의 MyISAM 테이블에서 트랜잭션을 사용하려고 시도하는 것입니다.

스크립트가 종료되거나 연결이 닫히려고 할 때 미해결 트랜잭션이 있는 경우 PDO는 자동으로 이를 롤백합니다. 이것은 스크립트가 예기치 않게 종료되는 경우 불일치를 방지하는 데 도움이 되는 안전 조치입니다. 트랜잭션을 명시적으로 커밋하지 않은 경우 문제가 발생한 것으로 간주되므로 데이터의 안전을 위해 롤백이 수행됩니다.

경고 자동 롤백은 PDO::beginTransaction()을 통해 트랜잭션을 시작한 경우에만 발생합니다. 트랜잭션을 시작하는 쿼리를 수동으로 실행하는 경우 PDO는 이에 대해 알 수 없으므로 나쁜 일이 발생하면 롤백할 수 없습니다.

예제 #1 트랜잭션에서 배치 실행

다음 샘플에서는 ID 번호 23이 할당된 새 직원에 대한 항목 집합을 생성한다고 가정합니다. 해당 직원의 기본 데이터를 입력하는 것 외에도 급여도 기록해야 합니다. 두 개의 개별 업데이트를 만드는 것은 매우 간단하지만 PDO::beginTransaction()PDO::commit() 호출 내에 포함하여 완료될 때까지 다른 누구도 이러한 변경 사항을 볼 수 없도록 보장합니다. 문제가 발생하면 catch 블록은 트랜잭션이 시작된 이후의 모든 변경 사항을 롤백한 다음 오류 메시지를 출력합니다.

                  
<?php
try {
  $dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
      array(PDO::ATTR_PERSISTENT => true));
  echo "Connected\n";
} catch (Exception $e) {
  die("Unable to connect: " . $e->getMessage());
}

try {
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $dbh->beginTransaction();
  $dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
  $dbh->exec("insert into salarychange (id, amount, changedate)
      values (23, 50000, NOW())");
  $dbh->commit();

} catch (Exception $e) {
  $dbh->rollBack();
  echo "Failed: " . $e->getMessage();
}
?>
                  
                

트랜잭션 업데이트에만 국한되지 않습니다. 또한 복잡한 쿼리를 실행하여 데이터를 추출하고 해당 정보를 사용하여 더 많은 업데이트 및 쿼리를 작성할 수도 있습니다. 트랜잭션이 활성 상태인 동안에는 다른 사람이 작업을 하는 동안 변경할 수 없습니다. 트랜잭션에 대한 자세한 내용은 데이터베이스 서버에서 제공하는 설명서를 참조하십시오.