【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发现不存在,于是重新生成了一个句柄,这个句柄是没开启事务的,然后抛出一场时事务回滚就提示上面的错误信息了

 

posted @   蓝色星辰1993  阅读(748)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示