PHP中使用PDO操作事务的一些小测试

关于事务的问题,我们就不多解释了,以后在学习 MySQL 的相关内容时再深入的了解。今天我们主要是对 PDO 中操作事务的一些小测试,或许能发现一些比较好玩的内容。

在 MyISAM 上使用事务会怎么样?

首先,相信只要是学过一点点的 MySQL 相关知识的人都知道,在 MySQL 中常用的两种表类型就是 InnoDB 和 MyISAM 这两种类型。当然,我们今天也不讲它们全部的区别,但有一个区别是最明显的,那就是 MyISAM 不支持事务。那么,如果我们在 PDO 操作中对 MyISAM 进行事务操作会怎么样呢?

// myisam
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_myisam (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_myisam2 (name, age) values ('Joe', 12, 33)");

    // sleep(30);
    $pdo->commit();

} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

登录后复制

tran_myisam 和 tran_myisam2 表都是 MyISAM 类型的表,在这段代码中,我们故意写错了 tran_myisam2 的插入语句,让它走到 catch 中。实际执行的结果是,报错信息正常输出,tran_myisam 表的数据也被插入了。也就是说,针对 MyISAM 表的事务操作是没有效果的。当然,PDO 也不会主动报错,如果我们让第二条 SQL 语句也是正常语句的话,PDO 只会正常执行结束,不会有任何的错误或者提示信息。

// innodb
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12, 3)");
    // sleep(30);
    $pdo->commit();

} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

登录后复制

我们可以打开 sleep(30); 这行代码的注释,也就是在事务提交前暂停 30 秒,然后在 MySQL 中查看 infomation_schema.INNODB_TRX 表。这个表中显示的就是正在执行中的事务。在 InnoDB 类型的表执行时就可以看到一条事务正在执行的记录,而 MyISAM 类型的表中则不会看到任何信息。

不提交不回滚事务会发生什么?

假设我们忘写了 commit() ,同时也没有报错,这条语句会执行成功吗?就像下面这段代码一样。

try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)");

    // 忘记写 $pdo->commit(); 了
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

登录后复制

PHP 会在脚本执行结束后,其实也就是在 $pdo 对象析构时回滚这个事务。也就是说,这里的 SQL 语句是不会执行的。但是,尽量不要这么做,因为在正式环境中,我们的代码非常复杂,而且不一定会析构成功。这样的话,可能会有长时间占据的事务存在,最终结果就是会导致 MySQL 的 IPQS 奇高,而且还很难找到原因。所以,在使用事务的时候,一定要记得 commit() 和 rollBack() 都是我们的亲兄弟,绝不能落下他们。

上一个事务没有提交没有回滚,下一个事务会执行吗?

同样的,在上一个问题的基础上我们再继续延伸。如果有两个事务依次执行,第一个事务没有提交,没有回滚,那么下一个事务还能执行吗?

// innodb
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)");
    // 忘记写 $pdo->commit(); 了
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

// innodb
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('BW', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('BW', 12)");

    // sleep(30);
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL; // Failed: There is already an active transaction
}

登录后复制

我们可以看到,第二段事务直接就报错了,内容是:“这里有一个已经存在的活动事务”。也就是说如果上一个事务没有提交没有回滚的话,第二个事务是无法执行的。

总结

今天我们只是学习并测试了几个事务相关的小问题,但问题虽小却有可能带来严重的线上事故,大家在开发的时候一定要小心。关于事务的详细内容在将来深入学习 MySQL 的时候我们再好好研究。

测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP中使用PDO操作事务的一些小测试.php

登录后复制

关于PHP中使用PDO操作事务的一些小测试的文章就分享到这,如果对你有帮助欢迎继续关注我们哦

本文来自投稿,不代表重蔚自留地立场,如若转载,请注明出处https://www.cwhello.com/244226.html

如有侵犯您的合法权益请发邮件951076433@qq.com联系删除

(0)
php学习php学习订阅用户
上一篇 2023年3月29日 23:09
下一篇 2023年3月29日 23:10

相关推荐

  • PHP中使用Redis实现分布式定时任务

    Redis是一种高性能的内存数据库,它具有快速的读写速度、支持一定级别的持久性和丰富的数据类型等优点。Redis常被用于缓存、消息队列、实时排行榜等场景。在开发中,我们有时会需要实现分布式的定时任务,比如:发…

    2023年5月19日
    01
  • 打造稳定和高质量的PHP直播功能。

    PHP是一种开放源代码的服务器端编程语言,适用于web开发。随着网络直播的迅速发展,越来越多的网站开始开发直播功能来吸引更多用户。要实现一个稳定和高质量的PHP直播功能,需要经过以下步骤。第一步——确定需求在实…

    2023年5月28日
    00
  • 详细介绍php 三种文件下载的实现

    本篇文章给大家详细介绍php 三种文件下载的实现有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。1、直接添加文件链接<button> <a href = "http://localhost/down.zip"> 下…

    2023年3月29日 PHP自学教程
    04
  • 我的PHP学习第二十二天之MySQL基础

    MySQL客户端下,操作MySQL的步骤 第一步:连接到MySQL数据库服务器       mysql –uroot -root 第二步:选择要操作的数据库(当前数据库)   use db_name 第三步:设置字符集   set names gbk 第四步:执行SQL语句:增…

    2016年5月14日 PHP自学教程
    0242
  • 详解php基于redis的list型数据结构实现ip限流操作

    在日常的业务功能开发中,如果要 限制任意一个ip在连续的某一段时间内,只能访问某个接口一定的次数,需要如何实现呢?这种功能需求通常是用来应对防止脚本恶意刷接口的情况,目前网上已经有很多比较完善的限流方案…

    2022年6月27日
    0122
  • PHP中如何进行区块链应用开发?

    随着区块链的发展,越来越多的开发者开始探索如何将其应用到实际场景中。PHP作为一种常用的服务器端脚本语言,也可以被用于区块链应用的开发。本文将介绍PHP中如何进行区块链应用开发。熟悉区块链的基本概念要进行…

    2023年5月17日
    04
  • 如何使用PHP实现微信小程序的AR功能。

    随着时代的发展,AR技术愈发成熟,不仅可以应用于游戏、广告等领域,还可以应用于生活中的各个方面。微信小程序是当前最流行的应用之一,许多企业也通过微信小程序向用户展示自己的产品和服务。那么,如何使用PHP实…

    2023年6月3日
    03
  • PHP实现MongoDB数据库异地容灾的方法。

    随着互联网应用规模的不断扩大,服务器数量的增加,数据的安全性和可靠性越来越受到重视。而异地容灾是一种重要的手段,可以避免单点故障导致的数据丢失和应用中断。本文将介绍如何使用PHP实现MongoDB数据库异地容…

    2023年5月21日
    03

联系我们

QQ:951076433

在线咨询:点击这里给我发消息邮件:951076433@qq.com工作时间:周一至周五,9:30-18:30,节假日休息