转自:http://www.jianshu.com/p/34261804bc45

1.数据库事务

事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。
事务具有以下4个基本特征:
● Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。
● Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。
● Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
● Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。

2.实现数据库事务管理的方式

2.1 编码式事务

在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关方法就是编码式事务管理。
编码式事务管理需要程序员在具体的业务代码中显式调用事务管理的相关方法,并显式地根据各种条件来判断是提交还是回滚。这种方式在业务简单的系统中还可应付,对于业务复杂的系统可能会因为少了某些条件判断导致错误的提交或回滚,尤其对于业务需求变动极其频繁的系统可能会因为判断条件没有及时根据业务的调整而修改而导致错误的提交和回滚。
由于编码式事务存在需要将事务管理与业务逻辑代码耦合,并且难以判断或及时更新回滚条件,甚至出现意料之外的事务嵌套等原因,因此不推荐使用编码式方式管理事务。

2.2 声明式事务

TP系统的声明式事务管理机制在底层是建立在TP框架的行为扩展机制之上的。其实质是在控制器的目标方法执行前开启事务,在执行完控制器的目标方法之后根据实际情形提交或回滚事务。

声明式事务最大的优点就是不需要在具体的业务逻辑代码中搀杂事务管理的代码,只需在模块配置中声明需要开启事务管理的方法,即可将事务运用到业务逻辑中。

3.TP项目的声明式事务处理机制的实现

1)在系统常量配置中增加两个常量:
// 开启数据库事务
define('DB_TRANS_ENABLE', true);
// 数据库事务全局标志
define('DB_TRANS_VAR', 'tx_comment');
2)在BaseModel中重载TP框架的Model类中的add、addAll、delete、execute、save方法

具体可查看相关代码。

3)在MyActionBeginBehavior的run方法中根据系统全局事务开关和模块配置判断是否开启数据库事务
// 开启数据库事务 by 凡墙<jihaoju@qq.com> 2015.09.14 18:05
$db_trans_enable = C('DB_TRANS_ENABLE');
if(defined('DB_TRANS_ENABLE') && DB_TRANS_ENABLE && is_array($db_trans_enable) && in_array(strtolower(CONTROLLER_NAME . '.' . ACTION_NAME), $db_trans_enable)) {
env(DB_TRANS_VAR, true);
M()->startTrans();
}
4)在MyActionEndBehavior的run方法中根据系统全局事务开关、模块配置以及环境变量DB_TRANS_VAR的值判断是否提交事务
// 处理数据库事务 by 凡墙<jihaoju@qq.com> 2015.09.14 18:05
$db_trans_enable = C('DB_TRANS_ENABLE');
if(defined('DB_TRANS_ENABLE') && DB_TRANS_ENABLE && is_array($db_trans_enable) && in_array(strtolower(CONTROLLER_NAME . '.' . ACTION_NAME), $db_trans_enable)) {
$tx_commit = env(DB_TRANS_VAR);
if ($tx_commit === false) {
// 回滚
M()->rollback();
} else {
// 提交事务
M()->commit();
}
}
5)强制回滚

在需要强制回滚的代码处将环境变量 DB_TRANS_VAR 的值设为 false,则系统将在目的方法结束后回滚。

4.存在的问题

4.1 数据库读写分离

数据库读写分离后,按TP框架的机制,一次请求将至少创建两个数据库连接,因此目前的声明式事务实现机制需要针对读连接和写连接分别根据需要管理事务。

4.2 事务控制的细度

和编码式事务相比,声明式事务的最细粒度只能浸入到控制器的方法级别,没法做到像编码式事务那样可以浸入到代码块级别,甚至无法做到对非控制器的方法的事务管理。
待扩展。

4.3 事务对数据的影响

幻读phantom read:事务1读取记录时事务2增加了记录并提交,事务1再次读取时可以看到事务2新增的记录;
不可重复读unrepeatable read:事务1读取记录时,事务2更新了记录并提交,事务1再次读取时可以看到事务
修改后的记录;
脏读dirty read:事务1更新了记录,但没有提交,事务2读取了更新后的行,然后事务T1回滚,现在T2读取无效。
幻读、不可重复读、脏读等问题可通过数据库的事务隔离级别解决,待优化。

需要注意的是,若在数据模型层对数据做了缓存处理,系统开启事务后可能导致“脏数据”的问题,因此对于一些重要数据字段的读写不能依赖于缓存中的数据。

4.4 分布式事务

数据库分库分表或系统采用微服务架构后将出现分布式事务问题。
待研究。

PHP系统声明式事务处理的更多相关文章

  1. JAVAWEB 一一 框架整合(SSH,Spring+Struts2+Hibernate IOC/DI AOP声明式事务处理 定时任务)

    package org.springframework.orm.hibernate3; import java.io.Serializable; import java.util.List; impo ...

  2. Spring3声明式事务处理事务无法回滚rollback分析(annotation与xml配置混用)

    新项目试运行,DBA提示生产数据库一个表的事务20分钟都未提交,分析过程如下: 1.查看日志log文件,最近20分钟是否有error日志: 2.发现某表有insert错误日志,初步判断由该表插入异常, ...

  3. Spring自学教程-声明式事务处理(六)

    Spring事务处理分两种: 一.编程式事务:在程序中控制事务开始,执行和提交: 1.1 使用TransactionTemplate, 使用回调函数执行事务,不需要显示开始事务,不需要显示提交事务,但 ...

  4. Spring Data JPA系列4——Spring声明式数事务处理与多数据源支持

    大家好,又见面了. 到这里呢,已经是本SpringData JPA系列文档的第四篇了,先来回顾下前面三篇: 在第1篇<Spring Data JPA系列1:JDBC.ORM.JPA.Spring ...

  5. Spring(四)Spring JdbcTemplate&声明式事务

    JdbcTemplate基本使用 01-JdbcTemplate基本使用-概述(了解) JdbcTemplate是spring框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装.spr ...

  6. 【spring基础】spring声明式事务详解

    一.spring声明式事务 1.1 spring的事务管理器 spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现.spring容器负责事物的 ...

  7. 9.spring:事务管理(下):声明式事务管理

    声明式事务管理 sprin的声明式事务是管理AOP技术实现的事务管理,其本质是是对方法前后进行拦截,然后 在目标方法开始之前创建或者加入一个事务,在执行完成目标方法之后根据执行情况提交或者回滚事务. ...

  8. spring声明式事务以及配置

    使用spring提供的事务处理机制的好处是程序员可以不用关心事务的切面了,只要配置就好了,可以少写代码. spring声明式事务处理 spring 声明:针对的是程序员,程序员告诉spring容器,哪 ...

  9. Spring添加声明式事务

    一.前言 Spring提供了声明式事务处理机制,它基于AOP实现,无须编写任何事务管理代码,所有的工作全在配置文件中完成. 二.声明式事务的XML配置方式 为业务方法配置事务切面,需要用到tx和aop ...

随机推荐

  1. sql server 2012 数据引擎任务调度算法解析(下)

    上次我们说到,sql server 2012的企业版的任务调度流程,一直到给新连接分配了scheduler,都是与以前的版本算法是一致的,只有在进行任务分配的时候,算法才有了细微的调整. 新算法的目的 ...

  2. Oracle 收缩数据文件

    Oracle数据库中当某些大数据表不再需要的时候,我们可以通过以下方式来进行清理: DROP TABLE TBL_TEST PURGE; 但是对应表空间(tablespace)中的磁盘空间并没有得到释 ...

  3. MMORPG大型游戏设计与开发(服务器 游戏场景 动态场景与副本)

    场景的内容讲解到今天算是暂时划上一个句号了,接下来为大家讲解的是AI部分(大型AI),如果有兴趣的朋友不妨持续关注这些文章,大家一起学习和进步.动态场景和副本是场景中特殊的类型,副本在这里想必已经是无 ...

  4. Machine Learning Algorithms Study Notes(5)—Reinforcement Learning

    Reinforcement Learning 对于控制决策问题的解决思路:设计一个回报函数(reward function),如果learning agent(如上面的四足机器人.象棋AI程序)在决定 ...

  5. CodeForces 485C Bits[贪心 二进制]

    C. Bits time limit per test1 second memory limit per test256 megabytes inputstandard input outputsta ...

  6. 图像旋转 OpenCV实现

    经常对一幅图像进行旋转操作,OpenCV中提供了很方便易用的仿射变换函数warpAffine, 通过getRotationMatrix2D可以得到放射变换矩阵(矩阵大小2x3) #include &l ...

  7. 使用axis2 soapmonitor监控soap数据

    Using the SOAP Monitor SOAPMonitor使用 使用SOAPMonitor axis2开发笔记-消息监控 WebService大讲堂之Axis2(10):使用soapmoni ...

  8. flask+sqlite3+echarts3 系统监控

    总的而言,分三部分: 1.监控器(monitor.py): 每秒获取系统的四个cpu的使用率,存入数据库. 2.路由器(app.py): 响应页面的ajax,获取最新的一条或多条数据. 3.页面(in ...

  9. JsonPropertyOrder无法为DTO对象进行属性排序

    在项目中,遇到一个问题,无论怎么设置JsonPropertyOrder,都无法正确实现排序功能,问题代码如下: @JsonPropertyOrder(value={"courseId&quo ...

  10. Eclipse JEE 安装JBPM 4.4 GPD

    回顾往昔,发现自己好久没写博客了,想想以前自己是多么热衷于写博客分享,虽然分享的都是比较基础的东西,但每每看到访问量不断增加的时候内心还是爽爽的. 时间过的真的很快,离开学校和团队已经一个月了.来到了 ...