【PHP】thinkphp3.2.5 - There is no active transaction问题
线上一段代码
1 2 3 4 5 6 7 8 9 | try { $uModel = M( 'Users' ); $uModel ->startTrans(); $userInfo = $uModel ->where([ 'user_id' => 3])->select(); throw new \Exception( '操作失败' ); } catch (\Exception $e ) { $uModel ->rollback(); var_dump( $e ->getMessage()); } |
提示信息:
1 2 3 4 5 6 7 8 9 10 11 12 | There is no active transaction FILE: /datas/www/fxk/ThinkPHP/Library/Think/Db/Driver .class.php(323) #0 /datas/www/fxk/ThinkPHP/Library/Think/Db/Driver.class.php(323): PDO->rollBack() #1 /datas/www/fxk/ThinkPHP/Library/Think/Model.class.php(1709): Think\Db\Driver->rollback() #2 /datas/www/fxk/Application/Cron/Controller/TestController.class.php(19): Think\Model->rollback() #3 [internal function]: Cron\Controller\TestController->run() #4 /datas/www/fxk/ThinkPHP/Mode/Cron/App.class.php(212): call_user_func_array(Array, Array) #5 /datas/www/fxk/ThinkPHP/Mode/Cron/App.class.php(99): Think\App::invokeAction('Test', 'run') #6 /datas/www/fxk/ThinkPHP/Mode/Cron/App.class.php(58): Think\App::exec() #7 /datas/www/fxk/ThinkPHP/Library/Think/Think.class.php(136): Think\App::run() #8 /datas/www/fxk/ThinkPHP/ThinkPHP.php(100): Think\Think::start() #9 /datas/www/fxk/cron.php(11): require('/datas/www/fxk/...') |
查看代码Driver.class.php 323
应该是$this->_linkID属性有问题,这个属性的定义是在initConnect方法,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | protected function initConnect( $master = true) { // 开启事物时用同一个连接进行操作 if ( $this ->transPDO) { return $this ->transPDO; } if (! empty ( $this ->config[ 'deploy' ])) // 采用分布式数据库 { $this ->_linkID = $this ->multiConnect( $master ); } else // 默认单数据库 if (! $this ->_linkID) { $this ->_linkID = $this ->connect(); } } |
如果存在 transPDO直接返回,这个属性是那里来的,请看(其实就是_linkID,用来判定是否在事务中,避免事务嵌套):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public function startTrans() { $this ->initConnect(true); if (! $this ->_linkID) { return false; } //数据rollback 支持 if (0 == $this ->transTimes) { // 记录当前操作PDO $this ->transPdO = $this ->_linkID; $this ->_linkID->beginTransaction(); \Think\Log::record( date ( 'H:i:s ' ) . 'begin;' , 'mysql' ); } $this ->transTimes++; return ; } |
发现问题,开启事务时候赋值的是transPdo,而在initConnect里面判断是transPDO,这点很有问题,但是为什么会导致这个报错,返回到调试代码,我们把代码简化,去掉查询后,执行正常,那问题可能就在执行了select()
在select中的query方法,调用了initConnect初始化,串联起来原因就出来了:开启事务的时候初始化了句柄存在transPdo,中间调用Select方法,判断的是transPDO发现不存在,于是重新生成了一个句柄,这个句柄是没开启事务的,然后抛出一场时事务回滚就提示上面的错误信息了
得意时做事,失意时读书
分类:
PHP
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律