`
flyPig
  • 浏览: 137136 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Transaction

    博客分类:
  • DB
阅读更多
事务具有四个特性
1. 原子性(Atomic):一个事务中所有对数据库的操作是一个不可分割的操作序列。这些操作要么完整的被全部执行,要么一步也不做。是一个逻辑工作单位。
2.一致性(Consistency):一个事务独立执行的结果将保持一致性,即数据不会因为事务的执行而遭受破坏。
3.隔离性(Isolated):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4.持久性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其执行结果有任何影响。

数据库并发性问题
脏读(dirty read):脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有commit到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。而后第一个事务又回滚了修改,则第二个事务持有的就是脏数据。

解决办法:如果在第一个事务提交前,任何其他事务不可读取其修改过的值,则可以避免该问题。

丢失更新(lost updates):当两个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。如图,事务A的操作就被事务B给覆盖掉了。

解决办法:对数据行加锁,只允许同时进行一个更新事务。

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

解决办法:如果只有在修改事务B提交之后事务A才可以读取数据,则可以避免该问题。

幻读(phantom read):第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.

解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据或者删除已有数据,则可避免该问题.

幻读和不可重复的区别在于
不可重复读是对要读的数据修改,导致同一事务内两次的读取结果不一致。
幻读是对表内的数据作insert/delete,导致同一事务内,两次select的结果记录数目有多或者少。

事务的隔离级别:
ISOLATION_READ_UNCOMMITTED(未提交读):这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。

ISOLATION_READ_COMMITTED(提交读): 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。它会锁定正在读取的行。

ISOLATION_REPEATABLE_READ(可重复读):这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免不可重复读。它会锁定所读取的所有行。

ISOLATION_SERIALIZABLE(序列化): 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。它会锁住整个表。

事务的传播属性
PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。这是最常见的选择方式。
PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。
PROPAGATION_MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务。
PROPAGATION_NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常
PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别:它们都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。
使用PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务commit后,外层事务不能对其进行rollback。两个事务之间互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。
使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED时,需要JDBC 3.0以上驱动及1.4以上的JDK版本支持。其它的JTA TrasactionManager实现可能有不同的支持方式。

一个自己画的简陋的状态图:
  • 大小: 7 KB
  • 大小: 9.6 KB
  • 大小: 9.1 KB
  • 大小: 9.1 KB
  • 大小: 27.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics