转自: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. [Django]数据批量导入

    前言:历经一个月的复习,考试终于结束了.这期间上班的时候有研究了Django网页制作过程中,如何将数据批量导入到数据库中. 这个过程真的是惨不忍睹,犯了很多的低级错误,这会在正文中说到的.再者导入数据 ...

  2. 使用Windbg在XP下Heap追踪失败的原因

    1.故事背景      最近同事的代码中碰到一个bug会导致奔溃的bug,从dump上看是由于某个对象的堆内存指针被释放了,但代码仍调用了该对象指针的虚函数,从而引起内存访问违法崩溃,由于该类被大量使 ...

  3. 面试问题2:给一个5G的大文件,保存的数据为32位的整型,找到所有出现次数超过两次的数字

    问题描述:给一个5G的大文件,保存的数据为32位的整型,找到所有出现次数超过两次的数字 大数据操作: 解决方法一: 依次遍历文件数据, 开始32二进制清0 每次读取一个数,先和二进制位与,如果为0 则 ...

  4. POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心

    题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的 ...

  5. BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Sta ...

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

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

  7. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  8. Hibernate组件映射

    Hibernate联合主键映射以及组件映射 在Hibernate中联合主键的形成有两种可能:一种是由多对多映射形成的,多对多映射会形成第三张表,一般来说第三张表的主键是由其他两张表的主键构成的(比如学 ...

  9. TortoiseSVN 中 一个 Merge revisions to.. 小坑

    注意: 不能只选头与尾svn号, 一定要全选 !!全选 !!全选 !!

  10. [译]React Context

    欢迎各位指导与讨论 : ) 前言 由于笔者英语和技术水平有限,有不足的地方恳请各位指出.我会及时修正的 O(∩_∩)O 当前React版本 15.0.1 时间 2016/4/25 正文 React一个 ...