Manuel Pear

Transactions

Transactions -- Performing transactions

Description

PEAR MDB2 defaults to auto-committing all queries. However using the beginTransaction() method one can open a new transaction and with the commit() and rollback() methods, a transaction is finished. These three methods optionally accept a string name of a savepoint to set, release or rollback to respectively. The method inTransaction() may be used to check if a transaction is currently open.

Exemple 39-1. Doing a transaction

  1. <?php
  2. // Create a valid MDB2 object named $mdb2
  3. // at the beginning of your program...
  4. require_once 'MDB2.php';  
  5.  
  6. $mdb2 =& MDB2::connect('pgsql://usr:pw@localhost/dbnam');  
  7. if (PEAR::isError($mdb2)) { 
  8.    die($mdb2->getMessage());  
  9. }  
  10.  
  11. // check if transaction are supported by this driver
  12. if (!$mdb2->supports('transactions')) { 
  13.    exit();  
  14. }  
  15.  
  16. // Open a transaction
  17. $res = $mdb2->beginTransaction();  
  18.  
  19. ..  
  20.  
  21. // check if we are inside a transaction and if savepoints are supported
  22. if ($mdb2->inTransaction() && $mdb2->supports('savepoints')) { 
  23.    // Set a savepoint
  24.    $savepoint = 'MYSAVEPOINT'; 
  25.    $res = $mdb2->beginTransaction($savepoint); 
  26.  
  27.    .. 
  28.  
  29.    // determine if the savepoint should be released or to rollback to the savepoint
  30.    if ($error_condition) { 
  31.       $res = $mdb2->rollback($savepoint); 
  32.    } else { 
  33.       $res = $mdb2->commit($savepoint); 
  34.    }  
  35. }  
  36.  
  37. ..  
  38.  
  39. // determine if the commit or rollback
  40. if ($error_condition) { 
  41.    $res = $mdb2->rollback();  
  42. } else { 
  43.    $res = $mdb2->commit();  
  44. }  
  45.  
  46.  
  47. ?> 
Avertissement

PEAR MDB2 does not emulate transactions or savepoints. This means that it depends on the underlying RDBMS (and in the case of MySQL the storage engines used) if transactions will be available in MDB2. Also note that some RDBMS implicitly commit transactions when executing DDL statements - notable exceptions are Oracle and PostgreSQL.

MDB2 also supports "nested" transactions using the beginNestedTransaction() method. Actually these are not true nested transactions as they are natively supported in Interbase for example. MDB2 maintains a counter of opened nested transactions. The transaction is finished once that counter is decremented back to 1 with completeNestedTransaction() calls. If the RDBMS supports savepoints then MDB2 will automatically set a savepoint on every call of the beginNestedTransaction() method after the initial call and will return the name. These savepoints are automatically released by the completeNestedTransaction() method. The name of these automatic savepoints are determined by the "savepoint_format" option and the nested transaction counter. The "savepoint_format" defaults to 'MDB2_SAVEPOINT_%s'.

If, after initially opening a nested transaction, an unexpected PEAR error is raised on the MDB2 instance the transaction is rolled back, otherwise it is commited at this point. Using the getNestedTransactionError() method it is possible to check if there has been an error inside the transaction. Alternatively a rollback can be forced using the failNestedTransaction(). This method optionally accepts a mixed parameter which will set the error to return if the getNestedTransactionError() method is called, as well as a second boolean parameter that optionally forces an immidiate rollback.

Exemple 39-2. Using emulated nested transactions

  1. <?php
  2.  
  3. $mdb2->beginNestedTransaction(); # open transaction
  4.  
  5. $query = "INSERT INTO autoinc (id) VALUES (?)";  
  6. $stmt = $mdb2->prepare($query);  
  7.  
  8. $stmt->execute(array(1));  
  9.  
  10. $savepoint = $mdb2->beginNestedTransaction(); # ignored / sets savepoint
  11.  
  12. ..  
  13.  
  14. // never true for this example
  15. if (false) { 
  16.    // raise an error
  17.    $error = $mdb2->raiseError(MDB2_ERROR, null, null, 'kaboom'); 
  18.    $mdb2->failNestedTransaction();  
  19. }  
  20.  
  21. if(($error = $mdb2->getNestedTransactionError())) { 
  22.    die($error->getUserinfo());  
  23. }  
  24.  
  25. $mdb2->completeNestedTransaction(); # ignored / releases savepoint
  26.  
  27. $stmt->execute(array(2));  
  28.  
  29. $mdb2->completeNestedTransaction(); # commit
  30.  
  31.  
  32. ?> 

Finally MDB2 supports setting the transaction isolation level as per the SQL 92 standard using the setTransactionIsolation() method. If a given RDBMS does not support a given isolation level but supports a higher more strict isolation level, then MDB2 silently uses that higher transaction level. Some RDBMS systems support additional options which are silently ignored if they are not supported.

Exemple 39-3. Setting the transaction isolation level

  1. <?php
  2.  
  3. $options = array('wait' => 'WAIT', 'rw' => 'READ WRITE');  
  4. $options = array('wait' => 'NO WAIT', 'rw' => 'READ ONLY');  
  5.  
  6. $isolation_level = READ UNCOMMITTED # (allows dirty reads)
  7. $isolation_level = READ COMMITTED # (prevents dirty reads)
  8. $isolation_level = REPEATABLE READ # (prevents nonrepeatable reads)
  9. $isolation_level = SERIALIZABLE # (prevents phantom reads)
  10. $mdb2->setTransactionIsolation($isolation_level, $options);  
  11.  
  12.  
  13. ?> 

Remonter Remonter
L'éditeur javascript - CSS - Gentoo - Tutoriaux PHP - Tutoriels PHP - Bretagne - php - Moto - Kit graphique