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

参考文档:

https://www.php.net/manual/zh/pdo.transactions.php

php pdo设置事物级别,PHP中使用PDO操作事务的一些小测试相关推荐

  1. Python中logging:设置打印级别,打印格式,打印颜色

    目录 前言 一.引入库 二.实现代码 三.运行结果 四.补充知识 logging模块的日志级别 前言 控制log的打印级别,打印格式,控制台根据log级别打印不同的颜色 一.引入库 import lo ...

  2. php pdo预处理查询,关于php:从PDO预处理语句中获取原始SQL查询字符串

    在对准备好的语句调用pdoStatement::execute()时,是否有方法执行原始SQL字符串?出于调试目的,这将非常有用. 对于php>=5.1,请查看php.net/manual/en ...

  3. 隔离区别对待?如何捆绑?Java中的jdbc数据库事务及其隔离级别

    文章目录 一.数据库事务简介 二.JDBC事务处理 三.事务的ACID属性 四.数据库的隔离级别 五.设置隔离级别 一.数据库事务简介 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态. 事务 ...

  4. 数据库零碎要点001_数据库的4大特性(原子性_持久性_隔离性_一致性)_数据库的隔离级别(脏读_幻读_不可重复读)_mysql如何设置隔离级别

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  5. 设置隔离级别实现并发控制

    13.4.4 设置隔离级别实现并发控制 http://book.51cto.com  2010-02-08 20:03  刘奎  清华大http://new.51c学出版社  我要评论(0) 摘要:& ...

  6. android 设置打印级别

    https://www.csdn.net/gather_27/MtTakg4sNjY3Ni1ibG9n.html 一.LK层: 首先,在LK中,有一个对log打印级别的控制文档,其路径一般为:vend ...

  7. html5ie11缩放,如何设置缩放级别Internet Explorer 9 - Browsers | Microsoft Docs

    如何在更高版本中设置Internet Explorer 9缩放级别 04/21/2020 本文内容 重要 2022 Internet Explorer 11 桌面应用程序将停用,2022 年 6 月 ...

  8. word2010设置多级别标题

     Word是我最长使用的办公软件,如何快速高效的为word设置多级别标题就显得非常重要. 今天仔细找了为标题样式设置多级别编号的相关技巧. 操作关键点: 1.为大纲设置多级别列表样式 2.将多级链 ...

  9. php pho 连接 MySQL_详解PHP中的PDO类_php技巧 - Pho

    $query = $db->query('SELECT * FROM `foods`'); $foods = $query->fetchAll(PDO::FETCH_CLASS, 'Foo ...

最新文章

  1. Google Inc.:Google APIs:23' 解决方案
  2. jQuery综合案例——打地鼠(教学版本·附源码)
  3. k8s滚动升级_k8s deployment 滚动更新
  4. cat命令详解_好程序员Python培训之详解eval好与坏
  5. 使用PowerShel导入和导出Hyper-v虚拟机
  6. 几个安卓 app 暴露超1亿用户的数据
  7. 使用python写机器学习算法遇到的问题
  8. iOS定时器NSTimer的使用方法
  9. .net快速开发平台,learun敏捷开发框架
  10. 广联达提示盗版文件修复工具
  11. pt-online-schema-change 脚本化
  12. 【Spring Boot】——集成JSON工具
  13. 方舟编译器只能编译Java_说说 方舟编译器
  14. python+opencv实现人脸识别|采用现成训练好的模型
  15. 【BDTC 2017】最后两天!BDTC大会抢票倒计时!
  16. 计算机游戏13关gongl,密室逃脱4之恐怖电影院第13关怎么过 第13关通关攻略
  17. ArcGIS加载天地图底图
  18. 行人检测0-05:LFFD-行人训练数据制作以及训练
  19. VisionPro 卡尺记分说明
  20. c语言:初识指针(一)

热门文章

  1. 工业以太网交换机MODBUS协议总线光纤转换器工厂控制系统
  2. 交换机工作原理及交换机的基本配置实验
  3. 工信部部长李毅中:警惕IBM智慧地球陷阱
  4. MATLAB视频运动目标检测参考源码
  5. 三阶魔方还原的13种程序实现
  6. python 循环语句结果存储_【零基础学Python】循环语句
  7. php设置ip防火墙iis,IIS防火墙使用教程
  8. 前端游戏巨制! CSS居然可以做3D游戏了
  9. matrix67文章学习
  10. C++上机练习:欧拉回路