PHPssm框架事务管理是如何处理MySQL事务多次开启和事务操作嵌套的?求ssm框架事务管理源码

PHP框架是如何处理MySQL事务多次开启和事务操作嵌套的?求框架源码 - mysql-php - ITkeyowrd
PHP框架是如何处理MySQL事务多次开启和事务操作嵌套的?求框架源码
推荐:/* MYSQL的事务处理主要有两种方法。 1、用begin,rollback,commit来实现 begin 开始一个事务 rollback 事务回滚 commit 事务确认 2、直接用set来改变mysql的自动
一般的PHP框架是如何处理MySQL事务多次开启和事务操作嵌套的?求框架源码
推荐:php操作mysql事务深度测试-老默 一 事务是什么?   正常的sql语句是一条一条的执行,各个sql之间互不影响。   事务的机制类似于一个黑盒,黑盒里的sql语句(
一般的PHP框架是如何处理MySQL事务多次开启和事务操作嵌套的求框架源码
相关阅读排行
相关内容推荐
请激活账号
为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。
您的注册邮箱:
如果您没有收到激活邮件,请注意检查垃圾箱。这篇文章主要介绍了PHP中实现MySQL嵌套事务的两种解决方案,本文分析了doctrine和laravel的实现方式,并提取出来分析和总结,需要的朋友可以参考下 一.问题起源 在MySQL的官方文档中有明确的说明不支持嵌套事务: Transactions cannot be nested. This is a consequence of the implicit commit performed for any current transaction when you issue a STAR
Copyright (C) , All Rights Reserved.
版权所有 闽ICP备号
processed in 0.053 (s). 8 q(s)2078人阅读
PHP开发(45)
一、问题起源
在MySQL的官方文档中有明确的说明不支持嵌套事务:
1. Transactions cannot be nested. This is a consequence of the implicit commit performed for any current transaction when you issue a START TRANSACTION statement or one of its synonyms.&
但是在我们开发一个复杂的系统时难免会无意中在事务中嵌套了事务,比如A函数调用了B函数,A函数使用了事务,并且是在事务中调用了B函数,B函数也有一个事务,这样就出现了事务嵌套。这时候其实A的事务就意义不大了,为什么呢?上面的文档中就有提到,简单的翻译过来就是:
1. 当执行一个START TRANSACTION指令时,会隐式的执行一个commit操作。 所以我们就要在系统架构层面来支持事务的嵌套。
所幸的是在一些成熟的ORM框架中都做了对嵌套的支持,比如doctrine或者laravel。接下来我们就一起来看下这两个框架是怎样来实现的。友情提示,这两个框架的函数和变量的命名都比较的直观,虽然看起来很长,但是都是通过命名就能直接得知这个函数或者变量的意思,所以不要一看到那么一大坨就被吓到了 :)
二、doctrine的解决方案
首先来看下在doctrine中创建事务的代码(干掉了不相关的代码):
* version 1
public function beginTransaction()
++$this-&_transactionNestingL
if ($this-&_transactionNestingLevel == 1) {
$this-&_conn-&beginTransaction();
} else if ($this-&_nestTransactionsWithSavepoints) {
$this-&createSavepoint($this-&_getNestedTransactionSavePointName());
这个函数的第一行用一个_transactionNestingLevel来标识当前嵌套的级别,如果是1,也就是还没有嵌套,那就用默认的方法执行一下START TRANSACTION就ok了,如果大于1,也就是有嵌套的时候,她会帮我们创建一个savepoint,这个savepoint可以理解为一个事务记录点,当需要回滚时可以只回滚到这个点。然后看下rollBack函数:
* version 1
public function rollBack()
if ($this-&_transactionNestingLevel == 0) {
throw ConnectionException::noActiveTransaction();
if ($this-&_transactionNestingLevel == 1) {
$this-&_transactionNestingLevel = 0;
$this-&_conn-&rollback();
$this-&_isRollbackOnly =
} else if ($this-&_nestTransactionsWithSavepoints) {
$this-&rollbackSavepoint($this-&_getNestedTransactionSavePointName());
--$this-&_transactionNestingL
$this-&_isRollbackOnly =
--$this-&_transactionNestingL
可以看到处理的方式也很简单,如果level是1,直接rollback,否则就回滚到前面的savepoint。然后我们继续看下commit函数:
* version 1
public function commit()
if ($this-&_transactionNestingLevel == 0) {
throw ConnectionException::noActiveTransaction();
if ($this-&_isRollbackOnly) {
throw ConnectionException::commitFailedRollbackOnly();
if ($this-&_transactionNestingLevel == 1) {
$this-&_conn-&commit();
} else if ($this-&_nestTransactionsWithSavepoints) {
$this-&releaseSavepoint($this-&_getNestedTransactionSavePointName());
--$this-&_transactionNestingL
算了,不费口舌解释这段了吧 :)
三、laravel的解决方案laravel的处理方式相对简单粗暴一些,我们先来看下创建事务的操作:
* version 1
public function beginTransaction()
if ($this-&transactions == 1)
$this-&pdo-&beginTransaction();
感觉如何?so easy吧?先判断当前有几个事务,如果是第一个,ok,事务开始,否则就啥都不做,那么为啥是啥都不做呢?继续往下看rollBack的操作:
* version 1
public function rollBack()
if ($this-&transactions == 1)
$this-&transactions = 0;
$this-&pdo-&rollBack();
明白了吧?只有当当前事务只有一个的时候才会真正的rollback,否则只是将计数做减一操作。这也就是为啥刚才说laravel的处理比较简单粗暴一些,在嵌套的内层里面实际上是木有真正的事务的,只有最外层一个整体的事务,虽然简单粗暴,但是也解决了在内层新建一个事务时会造成commit的问题。原理就是这个样子了,为了保持完整起见,把commit的代码也copy过来吧!
public function commit()
if ($this-&transactions == 1) $this-&pdo-&commit();
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:154555次
积分:2697
积分:2697
排名:第13832名
原创:91篇
转载:13篇
评论:74条
(2)(1)(2)(2)(19)(28)(20)(19)(16)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'欢迎您使用KPHP开源框架
kphp开源框架之MYSQL存储过程事例,包含事务,参数,嵌套调用,游标等
标签:kphp开源框架
MYSQL存储过程 &点击4589次 时间:
kphp开源框架之MYSQL存储过程事例,包含事务,参数,嵌套调用,游标等,主要介绍一下MYsql的一些常用的存储过程,补习一下Mysql的存储过程知识,方便我们进行网站开发,及一些开发中遇到程序实现很复杂而利用数据库的存储过程更加方便的问题。
kphp开源框架之MYSQL存储过程事例,包含事务,参数,嵌套调用,游标等,主要介绍一下MYsql的一些常用的存储过程,补习一下Mysql的存储过程知识,方便我们进行网站开发,及一些开发中遇到程序实现很复杂而利用数据库的存储过程更加方便的问题。
下面简单介绍一下MYSQL的存储过程:
drop procedure if exists pro_rep_shadow_&&
delimiter |&&
----------------------------------&&
-- rep_shadow_rs&&
-- 用来处理信息的增加,更新和删除&&
-- 每次只更新上次以来没有做过的数据&&
-- 根据不同的标志位&&
-- 需要一个输出的参数,&&
-- 如果返回为0,则调用失败,事务回滚&&
-- 如果返回为1,调用成功,事务提交&&
-- 测试方法&&
-- call pro_rep_shadow_rs(@rtn);&&
-- select @&&
----------------------------------&&
create procedure pro_rep_shadow_rs(out rtn int)&&
&&& -- 声明变量,所有的声明必须在非声明的语句前面&&
&&& declare iLast_rep_sync_id int default -1;&&
&&& declare iMax_rep_sync_id int default -1;&&
&&& -- 如果出现异常,或自动处理并rollback,但不再通知调用方了&&
&&& -- 如果希望应用获得异常,需要将下面这一句,以及启动事务和提交事务的语句全部去掉&&
&&& declare exit handler for s&&
&&& -- 查找上一次的&&
&&& select eid into iLast_rep_sync_id from rep_de_proc_log where tbl='rep_shadow_rs';&&
&&& -- 如果不存在,则增加一行&&
&&& if iLast_rep_sync_id=-1 then&&
&&&&& insert into rep_de_proc_log(rid,eid,tbl) values(0,0,'rep_shadow_rs');&&
&&&&& set iLast_rep_sync_id = 0;&&
&&& -- 下一个数字&&
&&& set iLast_rep_sync_id=iLast_rep_sync_id+1;&&
&&& -- 设置默认的返回值为0:失败&&
&&& set rtn=0;&&
&&& -- 启动事务&&
&&& -- 查找最大编号&&
&&& select max(rep_sync_id) into iMax_rep_sync_id from rep_shadow_&&
&&& -- 有新数据&&
&&& if iMax_rep_sync_id&=iLast_rep_sync_id then&&
&&&&&&& -- 调用&&
&&&&&&& call pro_rep_shadow_rs_do(iLast_rep_sync_id,iMax_rep_sync_id);&&
&&&&&&& -- 更新日志&&
&&&&&&& update rep_de_proc_log set rid=iLast_rep_sync_id,eid=iMax_rep_sync_id where tbl='rep_shadow_rs';&&
&&& -- 运行没有异常,提交事务&&
&&& -- 设置返回值为1&
&&& set rtn=1;&&
drop procedure if exists pro_rep_shadow_rs_&&
delimiter |&&
---------------------------------&&
-- 处理指定编号范围内的数据&&
-- 需要输入2个参数&&
-- last_rep_sync_id 是编号的最小值&&
-- max_rep_sync_id 是编号的最大值&&
-- 无返回值&&
---------------------------------&&
create procedure pro_rep_shadow_rs_do(last_rep_sync_id int, max_rep_sync_id int)&&
&&& declare iRep_operationtype varchar(1);&&
&&& declare iRep_status varchar(1);&&
&&& declare iRep_Sync_&&
&&& declare iI&&
&&& -- 这个用于处理游标到达最后一行的情况&&
&&& declare stop int default 0;&&
&&& -- 声明游标&&
&&& declare cur cursor for select id,Rep_operationtype,iRep_status,rep_sync_id from rep_shadow_rs where rep_sync_id between last_rep_sync_id and max_rep_sync_&&
&&& -- 声明游标的异常处理,设置一个终止标记&&
&&& declare CONTINUE HANDLER FOR SQLSTATE '02000' SET stop=1;&&
&&& -- 打开游标&&
&&& -- 读取一行数据到变量&&
&&& fetch cur into iId,iRep_operationtype,iRep_status,iRep_Sync_&&
&&& -- 这个就是判断是否游标已经到达了最后&&
&&& while stop && 1 do&
&&&&&&& -- 各种判断&&
&&&&&&& if iRep_operationtype='I' then&&
&&&&&&&&&&& insert into rs0811 (id,fnbm) select id,fnbm from rep_shadow_rs where rep_sync_id=iRep_sync_&&
&&&&&&& elseif iRep_operationtype='U' then&&
&&&&&&& begin&&
&&&&&&&&&&& if iRep_status='A' then&&
&&&&&&&&&&&&&&& insert into rs0811 (id,fnbm) select id,fnbm from rep_shadow_rs where rep_sync_id=iRep_sync_&&
&&&&&&&&&&& elseif iRep_status='B' then&&
&&&&&&&&&&&&&&& delete from rs0811 where id=iId;&&
&&&&&&&&&&&&&
&&&&&&& elseif iRep_operationtype='D' then&&
&&&&&&&&&&& delete from rs0811 where id=iId;&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&& -- 读取下一行的数据&&&
&&&&&&& fetch cur into iId,iRep_operationtype,iRep_status,iRep_Sync_&&
&&&& -- 循环结束&&
&&& -- 关闭游标&&
结束语:以上只是通过最简单的事例说明MYsql的存储过程,想进一步了解,需要大家不断的去实践学习。
学习指南:
知识总结:

我要回帖

更多关于 律师事务所框架 的文章

 

随机推荐