转自: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. Ubuntu安装Maven3

    先增加Maven3的源,在/etc/apt/sources.list中添加以下信息 deb http://ppa.launchpad.net/natecarlson/maven3/ubuntu pre ...

  2. 极客DIY:打造你的专属黑客U盘

    简介 由于“Bad USB漏洞”的存在,USB闪存驱动器也成了常见的攻击目标.Bad-USB让黑客可以重新编程微控器作为一个“人机界面装置”(HID)或键盘,然后在目标机器上执行自定义键盘敲击.这种情 ...

  3. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  4. hbase-site.xml中HBASE_CLASSPATH 的设置

    http://www.dataguru.cn/thread-95064-1-1.html

  5. 3357: [Usaco2004]等差数列

    3357: [Usaco2004]等差数列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 321  Solved: 153[Submit][Statu ...

  6. TCP协议的三次握手和四次挥手

    暂时需要的信息有: ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1 SYN(SYNchronization) : 在连接建立时用来同步序号.当SYN= ...

  7. redux middleware 的理解

    前言 这几天看了redux middleware的运用与实现原理,写了一个百度搜索的demo,实现了类似redux-thunk和redux-logger中间件的功能. 项目地址:https://git ...

  8. 使用Nancy.Host实现脱离iis的Web应用

    本篇将介绍如何使用Nancy.Host实现脱离iis的Web应用,在开源任务管理平台TaskManagerV2.0代码里面已经使用了Nancy.Host实现自宿主的Web应用.学习Nancy之前最好了 ...

  9. C#进阶系列——DDD领域驱动设计初探(五):AutoMapper使用

    前言:前篇搭建了下WCF的代码,就提到了DTO的概念,对于为什么要有这么一个DTO的对象,上章可能对于这点不太详尽,在此不厌其烦再来提提它的作用: 从安全上面考虑,领域Model都带有领域业务,让Cl ...

  10. JS/CSS缓存杀手——VS插件

    背景 前些天去考科目二,感觉经历了一场不是高考却胜似高考的考试(10年前的5分之差, 还是难以释怀)!    一行八人,就我学的时间最少(4天,8人一辆车),教练都觉得我肯定还得再来一次! 靠着运气和 ...