`

Transaction 事务

    博客分类:
  • J2EE
阅读更多
   
数据库事务四特性ACID:
原子性(Atomicity):事务中的操作为一个不可拆分的原子单元,要么全部执行,要么都不执行。
一致性(Consistency):一个事务执行前后数据库都必须处于一致性状态。“数据库的一致性状态”指的是数据完整且满足所有的完整性约束。为了保证数据库的这种一致性,如果一个事务在某步执行失败,则之前所有对数据库的修改必须回滚。
隔离性(Isolation):同时并发执行的多个事务是相互隔离的,不能影响到彼此的执行。即一个事务正在操作的数据应该封锁起来,不被其它企图进行修改的事务看到。
持久性(Durability):事务成功执行后它对数据库的修改是永久的,即使系统出现故障也不受影响。



隔离级别(Isolation Levels):
当并发执行的多个事务同时操作一样的数据时,可能会存在以下的并发异常(Concurrency Anomalies)(这里所说的修改都泛指Update/Insert/Delete):
脏读(Dirty Read):
一个事务读到了其他事务尚未提交的修改。若另一个事务回滚,第一个事务读到的就是彻头彻尾的脏数据。
丢失更新(Lost updates):
并发执行的两个事务都对同一条数据记录做了更新操作并提交,后面的事务提交覆盖了前面事务的提交结果。
不可重复读(Non-repeatable Read):
一个事务两次相同条件的查询读取之间,结果集中的某一条数据记录被另一个事务更新。第一个事务对这条数据记录两次的读取结果就出现了不一致,即该条记录第一次的读取值“不可重复(再现)”。
幻读(Phantom Read):
一个事务两次相同条件的查询读取之间,另一个事务增加或删除了符合第一个事务第一次读取结果的某几条数据记录。第一个事务两次读取到的结果集就出现了记录数上的不一致,产生同样的查询条件却"多了几条记录"或"少了几条记录"的幻觉。
引用
不可重复读和幻读很像,他们的区别再说的详细点:
不可重复读的重点是更新:同样的条件,你读取过的数据,再次读取出来发现值不一样了;
幻读的重点是新增或删除:同样的条件,第1次和第2次读出来的记录数不一样.

为了保证数据库事务四特性ACID中的隔离性,避免出现上面所说的这些并发异常,数据库的事务层面上可以:
确保事务未提交前的修改不被其他事务看到,就可以避免脏读;
事务锁定其正在操作的行(即加行级锁(Row-level lock)),就可以避免丢失更新、不可重复读和因删除而引发的幻读;
事务锁定其正在操作的表(即加表级锁(Table-level lock)),就可以完全避免丢失更新、不可重复读和幻读。
这正是数据库隔离级别的由来:
隔离级别是否存在脏读?是否存在丢失更新&不可重复读?是否存在幻读?举例
未提交读(READ_UNCOMMITTED)YYY
提交读(READ_COMMITTED)NYYOracle
可重复读(REPEATABLE_READ)NNYMysql
序列化读(SERIALIZABLE)NNN
隔离级别越高,容错能力自然越高,但并发性能越低;反之,隔离级别越低,并发性能越高。





Spring AOP 声明式事务管理(未完,或有错)
相较于硬编码方式实现的事务管理(如JDBC),基于Spring AOP来实现事务管理显然有巨大的优势,可以让我们从繁琐的事务处理代码中解放出来。区别于硬编码方式的事务管理(Programmatic Transaction Management),我们叫它声明式事务管理(Declarative Transaction Management)。
Spring声明式事务管理既可基于XML配置方式实现,亦可基于Annotation注解方式来实现。
你在使用Spring的声明式事务管理时,有以下几个问题就得搞清楚:
引用
参考的必要,贴一段典型的JDBC事务处理代码片断:http://topic.csdn.net/u/20090729/21/259c32d7-c89a-4726-9385-f024c75a47bf.html
try {
    conn =DriverManager.getConnection("url","username","userpwd";
    conn.setAutoCommit(false);//禁止自动提交,设置回滚点
    stmt = conn.createStatement();
    stmt.executeUpdate("alter table …"); //数据库更新操作1
    stmt.executeUpdate("insert into table …"); //数据库更新操作2
    conn.commit(); //事务提交
}catch(Exception ex) {  
  ex.printStackTrace();
  try {
      conn.rollback(); //操作不成功则回滚
  }catch(Exception e) {
        e.printStackTrace();
    }
}

1 对单个事务,其边界boundary,或说其scope在哪里?
页面硬编码的方式如JDBC,事务的边界起于conn.setAutoCommit(false),止于conn.commit()|conn.rollback(),spring的声明式事务,边界在哪里?
对单个事务,不考虑传播,Spring的声明式事务在指定方法执行前开启事务,指定方法执行后关闭事务。boundary就是方法的边界,scope也就是该方法里。
2 单个spring事务的粒度granularity,或说级别可以控制到什么范围?
对单个事务,页面硬编码方式可以在代码层面任意控制其粒度大小,spring声明式事务的粒度是如何的那?spring AOP的切入点只支持方法级的,所以基于此的声明式事务,在不考虑传播的情况下,其事务的粒度是方法级的,最小能控制到的就是整个方法内(The Spring Framework's declarative transaction management is similar to EJB CMT in that you can specify transaction behavior (or lack of it) down to individual method level. Ref http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#transaction-declarative
3 何时触发事务的commit或rollback?
典型的JDBC代码,我们在try里执行完数据库操作后commit,在catch到异常后rollback,那spring的声明式事务中,commit和rollback都是何时触发的那?
一个加了声明式事务的service方法,正确执行结束后commit;若有异常发生,按照spring的异常触发事务回滚策略回滚:http://wuaner.iteye.com/blog/583943
4 事务在方法间的传播?
JDBC的事务是通过Connection实例对象控制的(JDBC transactions are controlled through the Connection object),这也就意味着一个jdbc连接(Connection实例)只能工作在一个事务下(the connection can only work on one transaction at a time)。如果一个大的逻辑业务操作,需要调用多个CRUD方法,我们想让这多个方法在一个事务下,最终无非就是通过让他们公用一个Connection来实现 (例子: http://blog.csdn.net/qjyong/article/details/5464835)。既然spring的声明式事务,其事务边界就是添加了事务的方法的边界,那遇到平级多个方法调用、方法中调另一个方法等情况时,是怎么处理事务的那?这就要考虑spring的事务传播特性 Propagation:
传播特性说明
PROPAGATION_NEVERExecute non-transactionally, throw an exception if a transaction exists.
PROPAGATION_NOT_SUPPORTEDExecute non-transactionally, suspend the current transaction if one exists.
PROPAGATION_SUPPORTSSupport a current transaction, execute non-transactionally if none exists.
PROPAGATION_MANDATORYSupport a current transaction, throw an exception if none exists.
PROPAGATION_REQUIREDSupport a current transaction, create a new one if none exists.  (Default)
PROPAGATION_NESTEDExecute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.
PROPAGATION_REQUIRES_NEWCreate a new transaction, suspend the current transaction if one exists.
很多人都愿意在 <tx:method /> 或 @Transactional 上配置propagation为REQUIRED;spring默认的就是REQUIRED,我不知道这样做目的是什么。
NESTED和REQUIRES_NEW有什么区别呢?参见:
http://forum.spring.io/forum/spring-projects/data/7372-propagation-nested-versus-propagation-requires-new
引用
PROPAGATION_REQUIRES_NEW starts a new, independent "inner" transaction for the given scope. This transaction will be committed or rolled back completely independent from the outer transaction, having its own isolation scope, its own set of locks, etc. The outer transaction will get suspended at the beginning of the inner one, and resumed once the inner one has completed.

Such independent inner transactions are for example used for id generation through manual sequences, where the access to the sequence table should happen in its own transactions, to keep the lock there as short as possible. The goal there is to avoid tying the sequence locks to the (potentially much longer running) outer transaction, with the sequence lock not getting released before completion of the outer transaction.

PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. if the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction.

Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction.

For example, consider parsing a very large input file consisting of account transfer blocks: The entire file should essentially be parsed within one transaction, with one single commit at the end. But if a block fails, its transfers need to be rolled back, writing a failure marker somewhere. You could either start over the entire transaction every time a block fails, remembering which blocks to skip - or you mark each block as a nested transaction, only rolling back that specific set of operations, keeping the previous work of the outer transaction. The latter is of course much more efficient, in particular when a block at the end of the file fails.



Sources:
http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html
Spring @Transactional boundaries
http://stackoverflow.com/questions/6363683/springy-transactional-boundaries
Spring声明式事务管理源码解读之事务开始:
http://www.iteye.com/topic/87426
Spring声明式事务管理源码解读之事务提交:
http://www.iteye.com/topic/89072
分享到:
评论

相关推荐

    (精选)CHI协议,transaction事务汇总

    CHI协议,transaction事务汇总: 1.部分事务分为ptl/full ,这里不做区分。 2.事务名基本可以“望文生义”,也就是我们代码所推荐的“命名即注释”。 3.部分事务的行为并不完全确定,个人推测。 4.针对request type...

    Spring在Transaction事务传播行为种类

    Spring在Transaction事务传播行为种类,希望对大家有所帮助

    springboot-transaction事务

    springboot中事务的使用demo,用jpa链接的Mysql数据库.

    springtransaction 事务管理

    spring 事务管理工程,导入到MyEclipse 中既可以使用

    transaction事务

    数据库事务

    C# 执行Transaction事务的一般例子

    C# 执行Transaction事务的一般例子,创建SqlTransaction 对象并用SqlConnection对象的BeginTransaction()方法开始事务,将Transaction属性设置为上面所生成的SqlTransaction对象。 运行环境:Visual Studio2010

    TCC-Transaction分布式事务DEMO

    TCC-Transaction分布式事务DEMO,基于Mysql数据库的事务,包括分布式提交和回滚,例子完成,可以正常跑,基于Maven构建的项目

    数据库中英文术语对照.pdf

    aborted transaction 夭折的事务 Abstract Data Type (ADT) 抽象数据类型 access control 存取控制 access method 存取方法 ACID properties (事务的)ACID 特性 active database 主动数据库 aggregation ...

    Principles of transaction processing

    Principles of transaction processing Copyright © 2009 by Elsevier Inc. All rights reserved

    Transaction Rollback 事务 让你的对象支持事务

    难道只要数据库连接才支持事务?答案肯定不是,因为COM+同样支持事务,一般的对象要支持事务需要怎样处理? 自行实现所有细节,比如说银行的提款机模拟,在Withdraw的代码中检查支取金额后的余额或者检查支取金额的...

    PostgreSQL TRANSACTION(事务)

    PostgreSQL TRANSACTION(事务) TRANSACTION(事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的: 为...

    Transaction 分布式事物的应用举例

    自定义事物类,以及 System....System.Transactions 基础结构通过支持在 SQL Server、ADO.NET、MSMQ 和 Microsoft 分布式事务协调器 (MSDTC) 中启动的事务,使事务编程在整个平台上变得简单和高效、看来没别的对象了。

    SQLite 事务(Transaction)

    SQLite 事务(Transaction) 事务(Transaction)是一个对数据库执行工作单元。事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可以是由某种数据库程序自动完成。 事务...

    QT中sqlite多线程操作4个注意问题

    总结了一下Qt中sqlite多线程操作遇到的几个问题,希望能对有需要的朋友一点帮助 总结了一下Qt中sqlite多线程操作遇到的几个问题,希望能对有需要的朋友一点帮助

    SQL Server数据库P166 (3)ROLLBACK TRANSACTION将显式事务或隐式事务回滚到事务的结束.sql

    内容概述:SQL Server数据库相关内容,对应张磊著《SQL Server数据库应用技术项目化教程》中166页(3)ROLLBACK TRANSACTION将显式事务或隐式事务回滚到事务的结束所对应的源码。代码经个人运行后无误,如果下载后运行...

    Could not roll back Hibernate transaction.doc

    Could not roll back Hibernate transaction; nested exception is org.hibernate.TransactionException: JDBC rollback failed 这表明Hibernate事务回滚操作失败,导致事务不能正确回滚。 二、问题原因 该问题的...

    数据库中的事务、存储过程和触发器的简单使用

    什么是事务(Transaction)  指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)–也是由多个sql语句组成,必须作为一个整体执行  这些sql语句作为一个整体一起向系统提交,要么都执行、要么都不执行 ...

    laravel 解决多库下的DB::transaction()事务失效问题

    今天小编就为大家分享一篇laravel 解决多库下的DB::transaction()事务失效问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    CALL TRANSACTION USING... 参数祥解

    CALL TRANSACTION USING 语句是 ABAP 中提供的一个方便的执行批量输入的语句,使用它可以通过程序代码完成多个事务码的连续执行。BDC_TAB 是批输入任务表,网上有很多例子了,大家用到的时候可以搜索。用事务码 SHDB...

    Java Transaction API概述

    JTA(Java Transaction API)允许应用程序执行分布式事务处理--在两个或多个网络计算机资源上访问并且更新数据。JDBC驱动程序的JTA支持极大地增强了数据访问能力。本文的目的是要提供一个关于的Java事务处理API(JTA)...

Global site tag (gtag.js) - Google Analytics