为什么会提交以下 PDO 事务?

发布于 2024-09-11 21:09:28 字数 2199 浏览 3 评论 0原文

我认为这个问题本身是不言自明的。代码如下 -

<?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();
    }
?>

即使我回滚 catch 块内的事务,数据仍然会被插入到数据库中。为什么?

编辑

我从文档中添加以下几行< /a> 进一步说明 -

不幸的是,并不是每个数据库都支持事务,因此 PDO 需要 当您第一次打开时以所谓的“自动提交”模式运行 联系。自动提交模式意味着您运行的每个查询都有 它自己的隐式事务(如果数据库支持),或者不支持 如果数据库不支持事务,则事务。如果您需要 一个事务,你必须使用 PDO::beginTransaction() 方法来 发起一项。如果底层驱动不支持事务, 将抛出 PDOException(无论您的错误处理如何) 设置:这始终是一个严重的错误情况)。一旦你进入 一个事务,你可以使用 PDO::commit() 或 PDO::rollBack() 来完成 它,取决于您在期间运行的代码是否成功 交易。

另外,页面中的以下几行 -

bool PDO::beginTransaction  ( void  )

关闭自动提交模式。当自动提交模式关闭时, 通过 PDO 对象实例对数据库进行的更改不会 提交直到您通过调用 PDO::commit() 结束事务。 调用 PDO::rollBack() 将回滚对数据库的所有更改 并将连接返回到自动提交模式。

一些数据库,包括MySQL,会自动发出隐式的 当数据库定义语言 (DDL) 语句(例如)时 COMMIT DROP TABLE 或 CREATE TABLE 在事务内发出。这 隐式 COMMIT 将阻止您回滚任何其他更改 在事务边界内。

I think the question itself is pretty self-explanatory. The code is given below -

<?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();
    }
?>

Even if I am rolling back the transaction inside the catch block, data are still being inserted into the database. Why?

EDIT

I am adding the following few lines from the documentation for further clarification -

Unfortunately, not every database supports transactions, so PDO needs
to run in what is known as "auto-commit" mode when you first open the
connection. Auto-commit mode means that every query that you run has
its own implicit transaction, if the database supports it, or no
transaction if the database doesn't support transactions. If you need
a transaction, you must use the PDO::beginTransaction() method to
initiate one. If the underlying driver does not support transactions,
a PDOException will be thrown (regardless of your error handling
settings: this is always a serious error condition). Once you are in
a transaction, you may use PDO::commit() or PDO::rollBack() to finish
it, depending on the success of the code you run during the
transaction.

Also, the following lines from this page -

bool PDO::beginTransaction  ( void  )

Turns off autocommit mode. While autocommit mode is turned off,
changes made to the database via the PDO object instance are not
committed until you end the transaction by calling PDO::commit().
Calling PDO::rollBack() will roll back all changes to the database
and return the connection to autocommit mode.

Some databases, including MySQL, automatically issue an implicit
COMMIT when a database definition language (DDL) statement such as
DROP TABLE or CREATE TABLE is issued within a transaction. The
implicit COMMIT will prevent you from rolling back any other changes
within the transaction boundary.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

为人所爱 2024-09-18 21:09:28

您应该检查是否使用 INNODB 作为数据库类型。 MyISAM 不支持事务。

You should check that you are using INNODB as your database type. MyISAM does not support transactions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文