事务学习总结

来源:互联网 发布:java的方法名 编辑:程序博客网 时间:2024/05/26 15:53

1,事务的定义

  事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。如果事务开始到结束之间没有出现异常(由开发者自己指定),则正常提交事务;如果出现了指定的异常,那该次事务中执行的所有sql操作都应该回滚。
  简单地说,事务是一种机制,用以维护数据库中数据的一致性。

2,事务的生命周期

开始事务:begin transaction
提交事务:commit transaction
回滚事务:rollback transaction
此外,可以自定义保存点save point,并且回退到保存点

3,事务的四大特性

原子性、一致性、隔离性、持久性。这四个属性通常称为事务的ACID特性。

1)原子性(Atomic):一个事务是一个不可分割的工作单位,事务中包括的多个操作,要么都做,要么都不做。
2)一致性(Consistency):事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。比如银行转帐,在帐户转换和资金转移前,帐户处于有效状态。如果事务成功地完成,并且提交事务,则帐户处于新的有效的状态。如果事务出错,终止后,帐户返回到原先的有效状态。不能在事务完成后账户处于无效的状态。事务不负责实施数据完整性,而仅仅负责在事务提交或终止以后确保数据返回到一致状态。理解数据完整性规则并写代码实现完整性的重任通常落在开发者肩上,他们根据业务要求进行设计。
3)隔离性(Isolation):多个事务之间是相互隔离的,一个事务的执行不能被其他事务干扰。
4)持久性(Durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其他操作或故障不应该对其有任何影响。

4,事务的类型

编程式事务:通过直接编写代码来控制transacation的开启,提交和回滚。
声明式事务:通过xml或注解的方式声明整个方法是一个完整的事务。

5,事务的传播特性(propagation)

  在一个事务被调用时,调用者和被调用者之间的事务关系就是由事务的传播特性控制的,有以下几种传播特性:

PROPAGATION_REQUIRED:如果已经存在一个事务,则加入当前事务,使用一个事务;如果没有事务则开启一个新的事务。
PROPAGATION_SUPPORTS:如果已经存在一个事务,则加入当前事务,使用一个事务;如果没有事务,则非事务的执行。
PROPAGATION_MANDATORY:如果已经存在一个事务,则加入当前事务,使用一个事务;如果没有一个活动的事务,则抛出异常。
PROPAGATION_REQUIRESNEW:总是开启一个新的事务,如果已经存在一个事务,则将这个存在的事务挂起。
PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
PROPAGATION_NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常。
PROPAGATION_NESTED:嵌套事务,如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。

  Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。

6,事务并发和产生的问题

1)脏读(dirty read)

  脏读发生在一个事务读取了被另一个事务改写但尚未提交的数据时。如果这些改变在稍后被回滚了,那么第一个事务读取的数据就会是无效的。也叫Read uncommitted。

  一个很形象的故事:一个有结巴的人在饮料店柜台前转悠,老板很热情地迎上来:“喝一瓶?”,结巴连忙说:“我…喝…喝…”,老板麻利地打开易拉罐递给结巴,结巴终于憋出了他的那句话:“喝…喝…喝不起啊!”。在这个故事中,饮料店老板就对结巴进行了脏读。
  
来看取款事务和转账事务并发时引发的脏读场景:
这里写图片描述
  在这个场景中,B希望取款500元而后又撤销了动作,而A往相同的账户中转账100元,就因为A事务读取了B事务尚未提交的数据,因而造成账户白白丢失了500元。
2)不可重复读(Non-repeatable Reads)

  在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。 那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

假设A在取款事务的过程中,B往该账户转账100元,A两次读取账户的余额发生不一致:
这里写图片描述
  在同一事务中,T4时间点和T7时间点读取账户存款余额不一样。
3)幻读(phantom read)

  指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及 到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

  幻读一般发生在计算统计数据的事务中,举一个例子,假设银行系统在同一个事务中,两次统计存款账户的总金额,在两次统计过程中,刚好新增了一个存款账户,并存入100元,这时,两次统计的总金额将不一致:
这里写图片描述
  幻象读和不可重复读是两个容易混淆的概念,前者是指读到了其它已经提交事务的新增数据,而后者是指读到了已经提交事务的更改数据(更改或删除)。
  为了避免这两种情况,采取的对策是不同的。为防止读取到更改数据,只需要对操作的数据添加行级锁;为防止读取到新增数据或删除数据,则往往需要添加表级锁——将整个表锁定,防止新增和删除数据。

7,事务的隔离级别

  为了解决事务并发出现的问题,提出了事务的隔离级别,定义了以下5种事务隔离级别。简单理解,隔离级别是一个事务对其它事务的权限开放程度,在多事务并发时,一个事务对另一个事务操作的数据的读取权限。

  ISOLATION_DEFAULT:默认的隔离级别,使用数据库默认的事务隔离级别。
  ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。
  ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。可避免脏读。
  ISOLATION_REPEATABLE_READ:它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。这种事务隔离级别可以防止脏读,不可重复读,但是可能出现幻读。
  ISOLATION_SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。

  隔离级别越高,越能保证数据的完整性和一致性,保证读取到的数据的正确性,但是对并发性能的影响也越大,整个系统的并发效率和吞吐量。对于大多数应用程序,隔离级别设为Read Committed即可满足大部分需求,它能够避免脏读取,而且具有较好的并发性能。
这里写图片描述
这里写图片描述

0 0