2014-11-12 1 views
0

다른 코드 블록의 결과를 기반으로 PDO 트랜잭션을 롤백하려고합니다. 이것은 DB 삽입이 실패하더라도 훌륭하지만 "다른 것들"이 예외를 던지면 커밋을 롤백하지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?다른 코드 블록이 실패 할 경우 PDO 롤백

PHP 버전 5.4, 데이터베이스 commit()를 호출하면 효과적으로 그래서 rollBack()에 남아있는 데이터베이스 작업이없는 commit()에 대한 호출을 다음, beginTransaction()에 의해 이전에 시작된 열려있는 트랜잭션을 완료 MS SQL

<?php 
    try { 
     $dbh = new PDO($dataSource); 
     $dbh->beginTransaction(); 
     $sql = "INSERT INTO $table 
        (field1, field2, etc) 
       VALUES 
        (:field1, :field2, :etc)" 
     $stmt = $dbh->prepare($sql); 
     $stmt->bindParam(':field1', $data["field1"]); 
     $stmt->bindParam(':field2', $data["field2"]); 
     $stmt->bindParam(':etc', $data["etc"]); 
     $stmt->execute(); 
     $dbh->commit(); 

     //do some other stuff which can throw an Exception 
    } catch (Exception $e) { 
     //make sure we have something to roll back 
     try { $dbh->rollBack(); } catch (Exception $e2) {} 
     $log->logFatal("Error: controller.inc.php: " . $e->getMessage()); 
    } 
?> 
+3

커밋 후 향후 오류가 발생하면 'rollBack()'할 계획이 없다면 'commit()'할 수 없습니다. 당신은'commit()'을 다른 것들 다음에 일어나게 할 필요가있다. –

+0

감사! 약간의 녹슨 SQL. 전형적으로 commit() 자체로 에러를 잡아낼 실제 방법이없는 것이 일반적인가요? 나는 다른 코드를 취소 할 수 없기 때문에 (이메일 보내기) –

답변

1

입니다.

성공적인 커밋 후에 실행하려는 다른 코드가있는 경우 if() 블록에서 반환 값을 확인할 수 있습니다. PDO::commit()은 커밋 작업 자체가 실패한 경우 FALSE을 반환하므로 다른 예외가 발생하면 메일 동작을 방지 할 수 있습니다.

try { 
    $dbh = new PDO($dataSource); 
    $dbh->beginTransaction(); 
    // etc... 
    // etc... 

    // Attempt to commit, and do other actions if successful 
    if ($pdo->commit()) { 
    // Do other actions 
    // mail, etc... 
    } 
    else { 
    // Otherwise, throw another exception which your catch {} will handle 
    throw new Exception('Transaction was not committed'); 
    } 
} catch (Exception $e) { 
    // Docs are unclear on whether rollBack() will throw an error on failure 
    // or just return false. It is documented to throw an exception if 
    // no transaction is actually active. 
    try { $pdo->rollBack(); } catch (Exception $e2) {} 
    // Log your error, either a normal PDO error, or failed commit()... 
    $log->logFatal("Error: controller.inc.php: " . $e->getMessage()); 
    } 
} 
+0

Ooh 나는 당신의 마지막 코멘트 이후에 내가 가진 해결책보다 훨씬 더 좋아한다. 감사! –

관련 문제