模型事务操作
前言
事务操作在复杂的数据库操作的时候尤为重要,特别是在操作多张表的时候,如果某一步骤出错了,就会导致有脏数据,会很危险,比如A表操作完需要再操作B表,如果A表操作成功,B表操作失败,那么A表的数据需要回滚,否则A表就会有脏数据。这个时候事务处理就派上用场了。
1. Mysql数据库注意
使用事务处理的话,需要数据库引擎支持事务处理。比如 MySQL
的 MyISAM
不支持事务处理,需要使用 InnoDB
引擎。
使用navcat
工具的可以在设计表
中的选项
找到引擎
,修改为InnoDB
即可:
Tips: 每张数据表都需要单独修改
InnoDB
引擎。
2. thinkPHP模型使用事务
官方文档介绍的是Db
类操作数据库的事务处理,这里就不说了。这里介绍的是使用模型
操作数据库如何做。
举个简单的例子:
- 第一步,根据用户名、密码插入用户数据;
- 第二步,修改刚新增用户的手机号为123;
若其中一步操作失败则全部回滚,此用户数据删除。
控制器层
public function insert(){
// 演示数据
$data = [
"username" => "zhangsan",
"password" => "12313212"
];
$res = (new UserBis())->insertData($data);
if(!$res) {
return show(0, "新增失败");
}
return show(1,"新增成功");
}
Business层
<?php
namespace app\admin\business;
use app\common\model\mysql\User as UserModel;
use think\Exception;
class User extends BaseBis
{
protected $model = null;
public function __construct(){
$this->model = new UserModel();
}
public function insertData($data){
// 开启事务
$this->model->startTrans();
try {
$uid = $this->add($data);
if(!$uid){
return $uid;
}
$user = $this->model->find($uid);
$res = $user->save(["id"=>$uid,"phone_number"=>"123"]);
if(!$res){
throw new Exception("更新手机号失败");
}
// 提交事务
$this->model->commit();
}catch (Exception $e){
// 事务回滚
$this->model->rollback();
return false;
}
return true;
}
}
BaseBis层
<?php
namespace app\admin\business;
use think\Exception;
class BaseBis
{
protected $model;
public function add($data){
// 默认status字段赋值
$data['status'] = config("status.mysql.table_normal");
try {
$res = $this->model->save($data);
}catch (Exception $e){
return 0;
}
// 返回id
return $this->model->id;
}
}
为了验证回滚结果,我把第二次的数据库操作的结果设置为false
:
$res = $user->save(["id"=>$uid,"phone_number"=>"123"]);
// 模拟操作出错的情况
$res = false;
第1,2次正常处理,第3,4次修改为模拟出错的情况,第5次正常处理:
可以看到id
为9,10
的数据不存在,这就是回滚的效果,当第二次操作失败的时候第一次的操作也会回滚。