前言
Mysql
事务详细描述:
https://www.runoob.com/mysql/mysql-transaction.html
要想了解
TP6
事务操作,首先要知道什么是事务(即数据库事务)。
😃 举个例子,我们去银行转账,操作可以分为下面两个环节:
-
从第一个账户划出款项。
-
将款项存入第二个账户。
在这个过程中,两个环节是
关联
的。第一个账户划出款项必须保证正确的存入第二个账户,如果第二个环节没有完成,整个的过程都应该取消,否则就会发生丢失款项的问题。
整个交易过程,可以看作是一个事务,
成功则全部成功,失败则需要全部撤消
,这样可以避免当操作的中间环节出现问题时,产生数据不一致的问题。
数据库事务是一个逻辑上的划分,有的时候并不是很明显,它可以是一个操作步骤也可以是多个操作步骤。我们可以这样理解数据库事物:对数据库所做的一系列修改,在修改过程中,暂时不写入数据库,而是缓存起来,用户在自己的终端可以预览变化,直到全部修改完成,并经过检查确认无误后,一次性提交并写入数据库,在提交之前,必要的话所做的修改都可以取消。提交之后,就不能撤销,提交成功后其他用户才可以通过查询浏览数据的变化。
一、创建数据库表
我们先来创建一个表来模拟一下场景(用于后续代码演示),具体情况如图所示:
二、配置数据库
prefix
表前缀如果不配置,则无法使用
name()
。
建好表后,在
config/database.php
配置一下,注意配置一下表前缀
tp6_
。
'connections' => [
'mysql' => [
'type' => 'mysql',
'hostname' => '127.0.0.1',
'database' => 'demo',
'username' => 'root',
'password' => 'root',
'hostport' => '3306',
'params' => [],
'charset' => 'utf8',
'prefix' => 'tp6_',
'deploy' => 0,
'rw_separate' => false,
'master_num' => 1,
'slave_no' => '',
'fields_strict' => true,
'break_reconnect' => false,
'trigger_sql' => env('app_debug', true),
'fields_cache' => false,
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
],
],
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
三、更改数据库引擎
在
TP6
中使用事务处理的话,需要数据库引擎支持事务处理,拿
Mysql
举例,你需要将默认的数据库引擎改为
InnoDB
引擎才能使用。
哪个数据库表需要事务操作,就更改哪个表的数据库引擎。
【数据库表上右键】→【设计表】→【选项】→【引擎】→【InnoDB】
三、事务操作
官方文档:
https://www.kancloud.cn/manual/thinkphp6_0/1037573
TP6
提供了 3 种事务操作 API:
-
自动处理:transaction
-
手动处理:startTrans
-
分布式事务:本篇不谈
第一种,自动处理。
使用
transaction
方法操作数据库事务,当闭包中的代码发生异常会自动回滚,这种方法说白了就是让
TP6
自动处理:
<?php
namespace app\controller;
use think\facade\Db;
class Index
{
public function index()
{
Db::transaction(function(){
Db::name('user')
-> where('name', '马云')
-> save(['money' => Db::raw('money - 50')]);
Db::name('user')
-> where('name', '李嘉诚')
-> save(['money' => Db::raw('money + 50')]);
});
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
第二种,手动处理。
使用
startTrans | try | catch
方法处理数据库事务,跟自动处理类似,只不过是手动控制提交和回滚,能执行其他业务逻辑代码。
手动 / 自动基本相同,这里不再解释。
<?php
namespace app\controller;
use think\facade\Db;
class Index
{
public function index()
{
Db::startTrans();
try {
Db::name('user')
-> where('name', '马云')
-> save(['money' => Db::raw('money - 50')]);
Db::name('user')
-> where('name', '李嘉诚')
-> save(['money' => Db::raw('money + 50')]);
Db::commit();
}
catch (\Exception $e) {
Db::rollback();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
第三种。全局(分布式)事务。
主要是进行处理
跨库事务
,即
多个数据库进行事务交互
。
由于篇幅太长了,本文不继续写了,详细看文档,也很简单。
官方文档:
https://www.kancloud.cn/manual/thinkphp6_0/1037573