我认为这个问题本身就是不言自明的.代码如下 -
<?php
$PDO = NULL;
$pdo_dsn = 'mysql:host=localhost;dbname=pdo_test';
$pdo_persistence = array( PDO::ATTR_PERSISTENT => true );
$db_user = 'root';
$db_pass = '';
$db_query = "INSERT INTO person(name, address)
VALUES ('Mamsi Mamsi', 'Katabon')";
try
{
$PDO = new PDO($pdo_dsn, $db_user, $db_pass,
$pdo_persistence);
}
catch(PDOException $e)
{
echo "Error occured: ". $e->getMessage();
die();
}
$PDO->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
$PDO->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
try
{
$PDO->beginTransaction();
$PDO->exec($db_query);
throw new PDOException('Generated Exception');
$PDO->commit();
}
catch(PDOException $e)
{
echo "An error occured while doing a database transaction. The
error message is : ".$e->getMessage();
$PDO->rollBack();
die();
}
?>
Run Code Online (Sandbox Code Playgroud)
即使我在catch块中回滚事务,数据仍然被插入到数据库中.为什么?
编辑
我将从文档中添加以下几行以进一步说明 -
不幸的是,并非每个数据库都支持事务,因此当您第一次打开连接时,PDO需要以所谓的"自动提交"模式运行.自动提交模式意味着您运行的每个查询都有自己的隐式事务(如果数据库支持它),或者如果数据库不支持事务则没有事务.如果需要事务,则必须使用PDO :: beginTransaction()方法来启动事务.如果底层驱动程序不支持事务,则抛出PDOException(无论您的错误处理设置如何:这始终是一个严重的错误条件).进入事务后,您可以使用PDO :: commit()或PDO :: rollBack()来完成它,具体取决于您在事务期间运行的代码是否成功.
此外,此页面的以下行-
bool PDO::beginTransaction ( void )
Run Code Online (Sandbox Code Playgroud)
关闭自动提交模式.在关闭自动提交模式时,在通过调用PDO :: commit()结束事务之前,不会提交通过PDO对象实例对数据库所做的更改.调用PDO :: rollBack()将回滚对数据库的所有更改并将连接返回到自动提交模式.
当在事务中发出数据库定义语言(DDL)语句(如DROP TABLE或CREATE TABLE)时,某些数据库(包括MySQL)会自动发出隐式COMMIT.隐式COMMIT将阻止您回滚事务边界内的任何其他更改.