事务

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。

事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。

说到事务首先要说的就是事务的四大特性:

原子性:事务必须是原子工作单元,其中的数据修改要么全部执行,要么不全不执行

一致性:在事务完成时必须使所有的数据都处于一致的状态

隔离性:由并发事务所做的修改必须与其它任何并发事务相隔离

持久性:事务完成后,它对系统的影响是永久的

数据操作现象

  • 更新丢失:两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。

  这是因为没有对操作的数据加任何的锁,两个事务都可以同时对同一行数据进行操作。目前几乎所有的数据库都不允许出现这样的情况。

  • 脏读:脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。  这是因为只对更新的数据做了写锁,但是没有加读锁,导致一个事务中修改却未提交的数据可以被另外一个事务读取。

    时间

    取款事务A

    转账事务B

    T1

    开始事务

    T2

    开始事务

    T3

    查询账户余额为1000元    

    T4

     汇入100元把余额改为1100元

     

    T5

    查询账户余额为1100元

    T6

     撤销事务

     

    T7

    查询账户余额为1000元    

     

    T8

     

     提交事务

    T9

     
  • 不可重复读:是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。

  这是因为虽然对更新的数据做了读写锁,但是没有对读取的数据加锁,导致另外一个事务可以修改已经被本事务读取的数据。

  • 幻读:事务T1读取与搜索条件相匹配的若干行。事务T2以插入或删除行等方式来修改事务T1的结果集,然后再提交。

  这是因为没有彻底隔离多个不同事务之间的读取结果,要避免幻读,必须在一个事务对某部分数据读取之后,在这整个事务期间,每次读取返回的结果都是一致的。

时间

取款事务A

转账事务B

T1

开始事务

T2

 查询所有余额为1000元账户

开始事务

T3

往所有余额为1000元的账户汇入100元将余额变更为1100元

T4

 

增加一个账户,往账户中汇入1000元

T5

 提交事务

T6

查询仍有余额为1000元的账户

 

T7

 提交事务

 

T8

 

T9

 

隔离级别

  • 读未提交:Read Uncommitted:允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。
  • 读已提交:Read Committed:允许不可重复读取,但不允许脏读取。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

  • 可重复读取:Repeatable Read:禁止不可重复读取和脏读,但是有时可能出现幻影数据。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

  • 可序列化:Serializable:禁止不可重复读取、脏读和幻读,提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。

JavaEE事务

Java Transaction API (JTA)

JTA指的是Java事务接口,实现和事务控制的上层架构,大部分JavaEE应用都是基于JTA在系统中实现事务控制。

 UserTransaction 接口

 begin()
 commit()
 rollback()
 getStatus() 

Java Transaction Service (JTS)

JTS指的是Java事务服务,JTS作为JTA的底层支持,实现了具体的底层事务控制,属于应用容器实现的一部分。一般在开发过程中不会直接接触到这一层。

原文地址:https://www.cnblogs.com/zhaowencong/p/4055058.html