Yii2中事务的使用以及代码实例

yii2 transactions 根据场景值开启事务 阅读详情

前言

一般我们做业务逻辑,都不会仅仅关联一个数据表,所以,会面临事务问题。

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的一个逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

准备

  • 数据库引擎为innodb
  • 本文使用的yii版本为2.0.5,只要是2.0以上就没有问题
  • 运行环境为PHP7.0.0,Mysql5.6

Yii中的事务

处理异常



/**

* 测试事务

*/

public function actionTest(){

//创建事务

$tr = Yii::$app->db->beginTransaction();

try {

for($i=1;$i<=3;$i++){

$test = new Areas();

$test->name = 'name'.$i;

$test->sort=1;

if($test->save()){

echo "save $i | ";

}


}

$test = new Areas();

$test->name = 'ab'.$i;

$test->sorta=1; //写入不存在的字段

if(!$test->save()){

"save fail"; //如果没有写入就输出

}

//提交

$tr->commit();

} catch (Exception $e) {

//回滚

$tr->rollBack();

echo "rollback";

}

}

运行结果

save 1 | save 2 | save 3 | rollback
  • 1

注意,因为最后的数据没有插入成功,触发了事务的回滚,所以数据表没有新增数据产生。

触发事务回滚的原因是代码出现了异常(Exception)。

处理数据失败

一般来讲,我们的运行中的代码是不会出现这种明显的异常,这种异常会在开发测试过程中消灭掉。

而真正造成数据需要回滚的是我们的某个业务出现问题,导致没有写入部分的数据。



/**

* 测试事务

*/

public function actionTest(){

//创建事务

$tr = Yii::$app->db->beginTransaction();

try {

for($i=1;$i<=3;$i++){

$test = new Areas();

$test->name = 'name'.$i;

$test->sort=1;

if($test->save()){

echo "save $i | ";

}

}

$test = new Areas();

$test->name = null; //数据库设计name不能为空,人为造成写入失败。

$test->sort=1; //写入不存在的字段

if(!$test->save()){

echo "save fail"; //如果没有写入就输出

}

//提交

$tr->commit();

} catch (Exception $e) {

//回滚

$tr->rollBack();

echo "rollback";

}

}

运行结果如下,数据库插入了三条数据。

save 1 | save 2 | save 3 | save fail
  • 1

也就是说,如果因为业务逻辑导致某个数据表没有写入数据,也没有出现对应的回滚。

改进方案如下


/**

* 测试事务

*/

public function actionTest(){

//创建事务

$tr = Yii::$app->db->beginTransaction();

try {

for($i=1;$i<=3;$i++){

$test = new Areas();

$test->name = 'name'.$i;

$test->sort=1;

if($test->save()){

echo "save $i | ";

}

}

$test = new Areas();

$test->name = null; //数据库设计name不能为空,人为造成写入失败。

$test->sort=1; //写入不存在的字段

if(!$test->save()){

throw new \yii\db\Exception(); //手动抛出异常,再由下面捕获。

}

//提交

$tr->commit();

} catch (Exception $e) {

//回滚

$tr->rollBack();

echo "rollback";

}

}

运行结果如下,数据库没有插入新数据,事务被回滚。

save 1 | save 2 | save 3 | rollback
  • 1

分散的数据处理

由于实际项目的复杂程度,导致我们的数据库操作分散在不同的Model中。

所以,实际项目的代码不会是上面的样子。

模拟需求

接收参数:

  • 名字
  • 性别
  • 签名

业务处理流程:

  1. 接收参数
  2. 由发号器得到用户的uid,发号器对应数据表增加一位数字
  3. 把名字、性别、签名和上一步的uid写入用户信息表
  4. 初始化用户余额表

回滚触发时机:

  • 初始化余额表没有传入uid导出没有写入数据

实际代码



//Controller



/**

* 测试事务-注册用户

*/

public function actionReg()

{

//获取请求

$request = Yii::$app->request;

//设定返回格式

$response = Yii::$app->response;

$response->format = \yii\web\Response::FORMAT_JSON; //返回json


//测试代码,去掉验证身份步骤


$name = $request->get("name");

$gender = $request->get("gender");

$sign = $request->get("sign");


//测试代码,省略参数校验步骤


$tr = Yii::$app->db->beginTransaction();

try {

//得到uid

$uid = App::getSeNo();

UserProfile::add($uid, $name, $gender, 1, $sign);

$user_balance = UserBalance::initUserBalance($uid);

$tr->commit(); //提交数据

} catch (Exception $e) {

//回滚

$tr->rollBack();

return $e->getMessage(); //返回自定义异常信息

}

return $user_balance;

}


//UserProfile


/**

* 添加用户信息

* @param $user_id

* @param $nikename

* @param $gender

* @param $user_type

* @param string $intro

* @return UserProfile

* @throws \Exception

*/

public static function add($user_id, $nikename, $gender,$user_type,$intro="") {

$model = new UserProfile();

$model->gender = $gender;

$model->nikename = $nikename;

$model->user_id = $user_id;

$model->user_type=$user_type;

$model->intro=$intro;

$model->update_time = time();

$insert =$model->insert();

if(!$insert){

throw new Exception("没有写入用户资料");

}

return $model;

}


//UserBalance


/**

* 初始化用户的可提现余额

* @param $user_id

*/

public static function initUserBalance($user_id){

$info=self::find()->where(['user_id'=>$user_id])->one();


if(!$info ){

$model=new UserBalance();

$model->user_id = $user_id;

$model->price= "0";

$model->update_time=time();

$insert = $model->insert();

if(!$insert){

throw new Exception("没有初始化用户余额");

}

$info=$model;

}

return $info->attributes;

}

正常的结果如下

{"id":124,"user_id":1473179883,"price":"0","update_time":1473179883}
  • 1

如果把初始化用户余额部分的user_id没有传递成功,返回的结果如下

"没有初始化用户余额"
  • 1

我们可以针对具体情况定位到错误所在位置,及时修改。

事务(Transaction)

从上面的实际代码可以看出,创建了事务,只要在范围内,就算是引入的别的Model也能把异常NG返回,完成回滚操作。

一般情况下,整个Yii应用使用了同一个数据库连接,或者说是使用了单例。

而在yii\db\Connection中,又对事务对象进行了缓存:


class Connection extends Component

{

// 保存当前连接的有效Transaction对象

private $_transaction;


// 已经缓存有事务对象,且事务对象有效,则返回该事务对象

// 否则返回null

public function getTransaction()

{

return $this->_transaction && $this->_transaction->getIsActive() ? $this->_transaction : null;

}


// 看看启用事务时,是如何使用事务对象的

public function beginTransaction($isolationLevel = null)

{

$this->open();

// 缓存的事务对象有效,则使用缓存中的事务对象

// 否则创建一个新的事务对象

if (($transaction = $this->getTransaction()) === null) {

$transaction = $this->_transaction = new Transaction(['db' => $this]);

}

$transaction->begin($isolationLevel);

return $transaction;

}

}

因此,可以认为整个Yii应用,使用了同一个 Transaction 对象,也就是说, Transaction::_level 在整个应用的生命周期中,是有延续性的。 这是实现事务嵌套的关键和前提。

【PHP】Yii2中事务的使用以及代码实例 Yii2中事务的使用以及代码实例前言一般我们做业务逻辑,都不会仅仅关联一个数据表,所以,会面临事务问题。 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错 阅读详情

相关推荐

使用Yii2 Gii为Laravel框架生成代码的综合指南

Laravel是一个基于PHP的开源Web应用框架,以其优雅的语法和丰富的功能闻名。它旨在提供一个更简单、更有表达力的方式来构建复杂的Web应用程序。自2011年首次发布以来,Laravel因其所提供的功能强大且易于使用的工具,成为了PHP开发者社区中最受欢迎的框架之一。Yii2框架的应用生命周期是一个清晰的多阶段过程,从初始化请求直到最终响应被发送给用户。一个典型的请求处理流程如下:请求初始化:当Web请求到达时,Yii2首先会加载配置文件和启动引导程序。请求路由。

weixin_35794316的博客 986

在Yii2.0中如何实现5个数据库的事务操作?

比如,你想象一个场景,你在一个自动售货机买五瓶饮料,但是你的钱只够买四瓶。如果售货机没有事务处理,它可能会先给你四瓶饮料,然后因为钱不够就停止了,这样就不对了。但是,如果售货机有事务处理,它会先检查你的钱是否够买五瓶,如果不够,就一瓶都不给你;在Yii2.0中,如果你想对五个数据库的五张表进行事务操作,你首先需要确保这五个数据库都支持事务,并且你已经为它们分别设置了数据库连接。在Yii2中,事务操作主要是为了确保一系列数据库操作要么全部成功,要么全部失败,以保证数据的一致性。

长风破浪会有时的博客 574

不用公网IP!用Ollama+Chatbox搭建家庭AI助手(内网穿透方案对比)

本文详细介绍了如何利用Ollama和Chatbox在家庭局域网中搭建本地AI助手,无需公网IP即可实现内网穿透。通过对比不同穿透方案(如Tailscale、FRP等),提供最优配置建议,帮助用户低成本部署隐私安全的家庭AI系统,适用于智能家居、儿童教育等多种场景。

weixin_26765287的博客 460

yii mysql 事务处理_Yii2——使用数据库操作汇总(增删查改、事务)

本文介绍了 Yii2——使用数据库操作汇总(增删查改、事务),具体如下:对象操作查询//1.简单查询$admin=Admin::model()->findAll($condition,$params);$admin=Admin::model()->findAll("username=:name",array(":name"=>$username));$infoArr= NewsL...

weixin_28910411的博客 334

RDMA网络通信技术、NCCL集合通讯(GPU)

NCCL 是 NVIDIA 专为 GPU 设计的高性能集合通信库,用于优化多 GPU、多节点间的集体操作(如 AllReduce、Broadcast、AllGather 等),是深度学习分布式训练的核心组件。RDMA 允许计算机直接访问远程内存,无需 CPU 干预,大幅降低了网络通信的延迟和 CPU 开销。常见的 RDMA 实现包括。是两项关键技术,用于优化节点间数据传输效率和大规模并行计算性能。在高性能计算(HPC)、人工智能训练和数据密集型场景中,

weixin_42795092的博客 2422

从宁德新能源面试官视角,拆解Halcon/OpenCV图像处理工程师的硬核技能树(附避坑指南)

本文从宁德新能源面试官视角出发,详细拆解Halcon/OpenCV图像处理工程师的核心技能树,涵盖硬件选型、算法实现和系统工程思维三大能力维度。文章提供工业视觉工程师面试的实战避坑指南,包括硬件配置要点、算法优化技巧及职业发展路径,助力求职者系统提升图像处理专业技能。

weixin_28732953的博客 129

Yii2.0中使用事务的方法

第一种方法 public function saveUserAvatar($userId, $params) { $transaction = Yii::$app-&gt;db-&gt;beginTransaction(); try { $user = User::findOne($userId); $user-&gt;scenario = 'set-avatar'; $u...

醉春风的博客 1489

为什么Yii2的事务经常放在try...catch里面?底层原理是什么?

底层原理: Yii2的事务处理是建立在数据库的原生事务功能之上的。在数据库中,事务是一组数据库操作,要么全部成功执行,要么全部回滚,以确保数据库的一致性。块会捕获这些异常,并在异常处理代码中执行事务的回滚操作,以保证数据的正确性,同时避免因异常导致数据错误或丢失的情况发生。块中,是为了在处理数据库操作过程中可能发生的异常情况时,能够正确地回滚事务,确保数据的一致性和完整性。块中是一种良好的实践,可以有效地处理数据库操作中可能发生的异常情况,并保证数据的正确性。块中执行数据库操作时,如果发生了异常,

长风破浪会有时的博客 614

Lumerical Python API实战指南(一)——从数据优化到自动化工作流

本文是Lumerical Python API实战指南,旨在帮助用户从繁琐的手动仿真操作转向智能自动化工作流。文章详细介绍了API环境的零基础搭建、核心操作(会话管理、命令执行与数据交换),并通过参数扫描与自动化分析流水线的实战案例,展示了如何利用Python脚本实现从数据优化到自动化仿真的全过程,显著提升光子设计效率。

xxx12的博客 567

FPGA网络调试实战:基于88E1111和DP83867两款PHY芯片的SGMII-UDP数据回环对比与避坑指南

本文深入对比了88E1111与DP83867两款PHY芯片在SGMII-UDP数据回环中的性能差异,涵盖硬件设计、Vivado工程配置及调试技巧。通过实测数据揭示DP83867在吞吐量、延迟和功耗方面的优势,并提供FPGA网络调试中的常见问题解决方案,助力工程师高效完成项目开发。

weixin_31682031的博客 384

yii mysql 事务处理_Yii2中事务的使用实例代码详解

前言一般我们做业务逻辑,都不会仅仅关联一个数据表,所以,会面临事务问题。数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑...

weixin_29103603的博客 526

计量经济学——事件研究法/事件分析法

计量经济学——事件研究法/事件分析法

weixin_46189461的博客 6752

Yii框架事务的使用

Yii2中事务的使用以及代码实例 前言 一般我们做业务逻辑,都不会仅仅关联一个数据表,所以,会面临事务问题。 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全

等我变优秀 1103

别再死记硬背了!用Wireshark抓包实战,5分钟搞懂GRE、L2TP、IPsec的区别

本文通过Wireshark抓包实战,详细解析GRE、L2TP和IPsec三大隧道协议的核心差异与应用场景。从报文结构到配置示例,帮助网络工程师快速掌握这些协议的本质,提升VPN部署与故障排查能力。特别适合准备HCIP认证的工程师深化理解。

weixin_30352645的博客 439

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

YII2常用知识点总结

YII2常用知识点总结 (一)总结性语句 (1)经常看看yii源码比如vendor\yiisoft\yii2\web这个目录(很重要)下的文件中的方法(这些文件中的公共方法,大致看了下基本上都可以通过\Yii::$app->functionName()这种方式引用) (2)批量操作时一般会返回成功操作的行数; (3)尽量能用框架自带的CRUD方法就用框架的,除非sql语句非常复杂就自...

weixin_30371875的博客 297

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Yii2中事务的使用

官方是这样的 // $connection其实是数据库连接$transaction = $connection->beginTransaction(); try { $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute...

weixin_30335353的博客 499

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Yii2.0的事务嵌套

最近在项目的开发中使用事务踩坑较多,特此记录。 $tr = Yii::$app->db->beginTransaction(); try { if($this->delete() == false){ throw new \Exception(json_encode ($this->getErrors ())); } $res =...

yingbao620的博客 5747

Yii2 使用 RESTful 写API接口 实例

Yii2 使用 RESTful? 其实 Yii2 框架本身就对 RESTful 是友好支持的,具体可以看官方文档(http://www.yiichina.com/doc/guide/2.0/rest-quick-start),或者去看源码,都是可以的 创建一个控制器  我的工作目录如图所示 (首先, 参照下面的目录图片,可以看出,我创建了两个大的文件夹,v1,v2,目的是测试访问不同版

daxia_85的博客 2万+

Yii2 实例管理

Yii2 实例管理Yii2框架没有提供类似ZendFramework3中提供的ServiceManager.那么Yii2框架是如何管理对象实例的呢?长时间使用Yii2框架的童鞋一定已经适应了对象中的public变量,以及一个来自yii\base\Component的__set()魔术方法来完成对象构造的过程,但是新鸟如何使用这一切来实例化一个对象呢?Yii2最擅长的是extends多个对象使他们拥有

newlooc的博客 716

Yii2的事务处理方法代码示例

Yii2的事务处理方法代码示例关于使用数据库事务几项功能的改进示例代码 关于使用数据库事务几项功能的改进 首先,你现在可以像下面这样以回调形式的事务工作: $connection->transaction(function() { $order = new Order($customer); $order->save(); $order->addItems...

徊忆羽菲 327

Yii2 Multiple Input组件使用指南

Yii2 Multiple Input组件使用指南 Yii2 Multiple Input是一个用于Yii2框架的扩展组件,它允许在同一个表单中对多个模型实例进行处理。这对于需要一次性编辑、显示或验证多个数据项的场景尤其有用。该项目使用PHP作为主要编程语言,并且遵循Yii2框架的设计理念。 新手上手需要特别注意的三个问题 问题1:环境依赖和安装 由于Yii2 Multiple Input是为Yi...

gitblog_00382的博客 858

yii2如何处理各种各样复杂的数据库事务操作?使用场景是什么?底层原理是什么?

处理复杂数据库事务操作可以使用 Active Record、DB Component 和事务管理器来处理复杂的数据库事务操作。Active Record 提供了简单的方法来处理事务,DB Component 提供了更细粒度的控制,事务管理器提供了统一的事务管理机制。使用场景多表操作、批量操作、复杂业务逻辑等。底层原理使用类管理事务,通过commit(), 和rollBack()方法实现事务的开始、提交和回滚。使用try-catch语句捕获异常,确保数据的一致性。类管理数据库连接,

长风破浪会有时的博客 1347

Yii2 事务操作

官网关于Yii2 事务的说明文档 http://www.yiiframework.com/doc-2.0/guide-db-active-record.html Working with Transactions There are two ways of usingtransactionswhile working with Active Record. The fi...

diandu3502的博客 180
上一篇: bash: docker-machine: command not found
下一篇: 如何运行vue项目
firstcode666
博客等级 码龄5年 53粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值