Here is a way of testing that your transaction has started when using MySQL's InnoDB tables. It will fail if you are using MySQL's MyISAM tables, which do not support transactions but will also not return an error when using them.
<?
// Begin the transaction
$dbh->beginTransaction();
// To verify that a transaction has started, try to create an (illegal for InnoDB) nested transaction.
// If it works, the first transaction did not start correctly or is unsupported (such as on MyISAM tables)
try {
$dbh->beginTransaction();
die('Cancelling, Transaction was not properly started');
} catch (PDOException $e) {
print "Transaction is running (because trying another one failed)\n";
}
?>
PDO::rollBack
(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0)
PDO::rollBack — トランザクションをロールバックする
説明
bool PDO::rollBack
( void
)
PDO::beginTransaction() によって開始された 現在のトランザクションをロールバックします 有効なトランザクションがない場合にこのメソッドをコールすると エラーになります。
データベースがオートコミットモードに設定されている場合、 この関数はトランザクションをロールバックした後に オートコミットモードを元に戻します。
MySQL を含むいくつかのデータベースでは、DROP TABLE や CREATE TABLE のようなデータベース定義言語 (DDL) ステートメントがトランザクション中に 発行される場合、暗黙的なコミットが自動的に発行されます。 この暗黙的なコミットにより、そのトランザクション境界で 他のあらゆる変更をロールバックすることができなくなるでしょう。
返り値
成功した場合に TRUE を、失敗した場合に FALSE を返します。
例
例1 トランザクションをロールバックする
以下の例は、トランザクションを開始し、 変更をロールバックする前にデータベースを修正する 2 つのステートメントを発行します。 しかしながら MySQL では、DROP TABLE ステートメントは 自動的にトランザクションをコミットするので、 トランザクション中のどの変更もロールバックされません。
<?php
/* トランザクションを開始する。オートコミットがオフになる */
$dbh->beginTransaction();
/* データベーススキーマとデータを変更する */
$sth = $dbh->exec("DROP TABLE fruit");
$sth = $dbh->exec("UPDATE dessert
SET name = 'hamburger'");
/* ミスに気づき、変更をロールバックする */
$dbh->rollBack();
/* データベース接続はオートコミットモードに戻る */
?>
PDO::rollBack
brian at diamondsea dot com
25-Mar-2008 03:19
25-Mar-2008 03:19
JonasJ
08-Jan-2008 09:59
08-Jan-2008 09:59
Just a quick (and perhaps obvious) note for MySQL users;
Don't scratch your head if it isn't working if you are using a MyISAM table to test the rollbacks with.
Both rollBack() and beginTransaction() will return TRUE but the rollBack will not happen.
Convert the table to InnoDB and run the test again.
linfo2003 at libero dot it
30-May-2007 02:07
30-May-2007 02:07
Since "It is an error to call this method if no transaction is active", it could be useful (even if not indispensable) to have a method which returns true if a transaction is active.
try {
$dbh->beginTransaction();
...
} catch (PDOException $e) {
if ($dbh->isTransactionActive()) // this function does NOT exist
$dbh->rollBack();
...
}
In the meanwhile, I'm using this code:
...
} catch (PDOException $e) {
try { $dbh->rollBack(); } catch (Exception $e2) {}
...
}
It's not so chic, but it works fine.
emalinks at gmail dot com
14-Apr-2007 08:09
14-Apr-2007 08:09
<?php
//run this on your latest PHP let me know if it doesn't fail
//to test this program u must run it twice at the same time in ie. two terminals
//this program suposedly creates a new dbase with table name NodeNames and one field in it named NodeName
//it then begins a transaction then attempts to read an element 'zTest' of field 'NodeName' which obv. doesn't exist, ignoring the returned errors
//then it writes it(since it wasn't there)
//then decides to rollBack the transaction and eventually try a new one
//because rollBack doesn't really work(apparently) for some unknown reason, beginTransaction fails saying 'There is already an active transaction'
$db = new PDO('sqlite:demlinks6.3sql',''/*user*/,''/*pwd*/);
$db->exec('CREATE TABLE \'NodeNames\' ("NodeName" VARCHAR(10));');
$db->beginTransaction();
$getter="zTest";
$pgn = $db->prepare('SELECT * FROM \'NodeNames\' WHERE "NodeName" = :node13');
$pgn->bindParam(":node13", $getter, PDO::PARAM_STR);
//read
$pgn->execute();//execute above SELECT
$ar=$pgn->FetchAll();//get array of results
$writter="zTest";
$pnn=$db->prepare('INSERT INTO \'NodeNames\' ("NodeName") VALUES (:node14)');
$pnn->bindParam(":node14", $writter, PDO::PARAM_STR);
//write
$pnn->execute();//write it!
echo "waiting...";
usleep(2000000);
echo "done\n";
$db->rollBack();//this doesn't do it's job
$db->beginTransaction();//here it fails, when running this program twice at the same time; 'There is already an active transaction'
//unreachable:
$db->commit();
?>
