Thinkphp 6 - 事务操作(自动(transaction) / 手动(startTrans))

前言

Mysql 事务详细描述:https://www.runoob.com/mysql/mysql-transaction.html

要想了解 TP6 事务操作,首先要知道什么是事务(即数据库事务)。


😃 举个例子,我们去银行转账,操作可以分为下面两个环节:

  1. 从第一个账户划出款项。
  2. 将款项存入第二个账户。

在这个过程中,两个环节是 关联 的。第一个账户划出款项必须保证正确的存入第二个账户,如果第二个环节没有完成,整个的过程都应该取消,否则就会发生丢失款项的问题。

整个交易过程,可以看作是一个事务,成功则全部成功,失败则需要全部撤消,这样可以避免当操作的中间环节出现问题时,产生数据不一致的问题。

数据库事务是一个逻辑上的划分,有的时候并不是很明显,它可以是一个操作步骤也可以是多个操作步骤。我们可以这样理解数据库事物:对数据库所做的一系列修改,在修改过程中,暂时不写入数据库,而是缓存起来,用户在自己的终端可以预览变化,直到全部修改完成,并经过检查确认无误后,一次性提交并写入数据库,在提交之前,必要的话所做的修改都可以取消。提交之后,就不能撤销,提交成功后其他用户才可以通过查询浏览数据的变化。

一、创建数据库表

我们先来创建一个表来模拟一下场景(用于后续代码演示),具体情况如图所示:
在这里插入图片描述

二、配置数据库

prefix 表前缀如果不配置,则无法使用 name()

建好表后,在 config/database.php 配置一下,注意配置一下表前缀 tp6_

// 数据库连接配置信息
'connections' => [

    'mysql' => [
        // 数据库类型
        'type'              => 'mysql',
        // 服务器地址
        'hostname'          => '127.0.0.1',
        // 数据库名
        'database'          => 'demo',
        // 用户名
        'username'          => 'root',
        // 密码
        'password'          => 'root',
        // 端口
        'hostport'          => '3306',
        // 数据库连接参数
        'params'            => [],
        // 数据库编码默认采用utf8
        'charset'           => 'utf8',
        // 数据库表前缀
        'prefix'            => 'tp6_',

        // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
        'deploy'            => 0,
        // 数据库读写是否分离 主从式有效
        'rw_separate'       => false,
        // 读写分离后 主服务器数量
        'master_num'        => 1,
        // 指定从服务器序号
        'slave_no'          => '',
        // 是否严格检查字段是否存在
        'fields_strict'     => true,
        // 是否需要断线重连
        'break_reconnect'   => false,
        // 监听SQL
        'trigger_sql'       => env('app_debug', true),
        // 开启字段缓存
        'fields_cache'      => false,
        // 字段缓存路径
        'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
    ],
    
],

三、更改数据库引擎

TP6 中使用事务处理的话,需要数据库引擎支持事务处理,拿 Mysql 举例,你需要将默认的数据库引擎改为 InnoDB 引擎才能使用。

哪个数据库表需要事务操作,就更改哪个表的数据库引擎。

【数据库表上右键】→【设计表】→【选项】→【引擎】→【InnoDB】

在这里插入图片描述

三、事务操作

官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037573

TP6 提供了 3 种事务操作 API:

  1. 自动处理:transaction
  2. 手动处理:startTrans
  3. 分布式事务:本篇不谈

第一种,自动处理。

使用 transaction 方法操作数据库事务,当闭包中的代码发生异常会自动回滚,这种方法说白了就是让 TP6 自动处理:

// 创建一个控制器来测试

<?php

namespace app\controller;
use think\facade\Db;

class Index
{

    /**
     * 事务: 马云转账给李嘉诚50元
     *
     * @return void
     */
    public function index()
    {

        /**
         * 事务处理类(transaction)-【自动】
         * @闭包中代码发生异常后自动回滚
         * 
         * ------------ 假设条件 ----------------
         * @当执行语句马云账户-50后
         * @李嘉诚+50那句代码因各种原因导致执行失败后
         * 
         * ------------ 最终结果 ----------------
         * @马云的账户不会-50(因为回滚了)
         * @李嘉诚更不会加(因为没执行)
         */
        Db::transaction(function(){

            // 马云账户 -50
            Db::name('user')//demo数据库tp6_user表
                -> where('name', '马云')//条件(name="马云")
                -> save(['money' => Db::raw('money - 50')]);//更新数据
        
            // 李嘉诚账户 +50
            Db::name('user')
                -> where('name', '李嘉诚')
                -> save(['money' => Db::raw('money + 50')]);
            
        });
    }

}

在这里插入图片描述


第二种,手动处理。

使用 startTrans | try | catch 方法处理数据库事务,跟自动处理类似,只不过是手动控制提交和回滚,能执行其他业务逻辑代码。

手动 / 自动基本相同,这里不再解释。

<?php

namespace app\controller;
use think\facade\Db;

class Index
{

    /**
     * 事务: 马云转账给李嘉诚50元
     *
     * @return void
     */
    public function index()
    {
        
        /**
         * 事务处理类(startTrans)-【手动】
         */
        Db::startTrans();

        /**
         * 执行正常(提交事务)
         */
        try {
            
            // 马云账户 -50
            Db::name('user')
                -> where('name', '马云')
                -> save(['money' => Db::raw('money - 50')]);

            // 李嘉诚账户 +50
            Db::name('user')
                -> where('name', '李嘉诚')
                -> save(['money' => Db::raw('money + 50')]);

            // 提交事务
            Db::commit();
        }

        /**
         * 执行不正常(执行失败)
         */
        catch (\Exception $e) {##这里参数不能删除($e:错误信息)

            // 做一些业务逻辑(包括反馈提示等)
            // ...

            // 回滚事务
            Db::rollback();
        }
    }
}

第三种。全局(分布式)事务。

主要是进行处理 跨库事务,即 多个数据库进行事务交互

由于篇幅太长了,本文不继续写了,详细看文档,也很简单。

官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037573

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王佳斌

请作者喝杯咖啡 :)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值