Should anyone reading this be slightly panicked because they just discovered that their MySQL tables are MyIsam and not InnoDb, don't worry... You can very easily change the storage engine using the following query:
ALTER TABLE your_table_name ENGINE = innodb;
PDO::rollBack
(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0)
PDO::rollBack — Bir toplu hareketi geri alır
Açıklama
PDO::beginTransaction() ile başlatılan toplu hareketi geri alır. Bir toplu hareket etkin değilken bu yöntemin çağrılması bir hataya sebep olur.
Eğer veritabanı özdevinimli gönderim kipindeyse, toplu hareket geri alındıktan sonra tekrar özdevinimli gönderim kipine dönülür.
MySQL dahil bazı veritabanları, bir toplu hareketin içinde DROP TABLE veya CREATE TABLE gibi bir veritabanı tanımlama dili deyimi kullanıldığında özdevinimli olarak örtük bir PDO::commit() yaparlar. Örtük PDO::commit(), toplu hareket içindeki diğer değişikliklerin de geri alınmasına engeller.
Dönen Değerler
Başarı durumunda TRUE, başarısızlık durumunda FALSE döner.
Örnekler
Örnek 1 - Bir toplu hareketin geri alınması
Aşağıdaki örnekte bir toplu hareket başlatılmakta, değişiklikleri geri almadan önce veritabanında değişiklik yapan iki deyim gönderilmektedir. Bununla birlikte MySQL'de, DROP TABLE deyimi hareketi özdevinimli olarak COMMIT ettiğinden toplu harekete dahil hiçbir değişiklik artık geri alınamaz.
<?php
/* Özdevinimli gönderimi kapatıp bir hareket başlatalım */
$dbh->beginTransaction();
/* Veritabanı şemasını ve verisini değiştirelim */
$sth = $dbh->exec("DROP TABLE fruit");
$sth = $dbh->exec("UPDATE dessert
SET name = 'hamburger'");
/* Yanlışı farkedip değişiklikleri geri alıyoruz */
$dbh->rollBack();
/* Veritabanı bağlantısı şimdi özdevinimli gönderim kipinde */
?>
Ayrıca Bakınız
- PDO::beginTransaction() - Bir toplu hareketi ilklendirir
- PDO::commit() - Bir toplu hareketi veritabanına gönderir
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";
}
?>
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.
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.
<?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();
?>
