数据库事务管理
一,数据库事务的定义
总得来说,事务是为了保证数据的安全性,一致性,正确性。必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性
1. 原子性(atomic),事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行
2. 一致性(consistent),事务的执行结果,必须是从一个一致状态,变成另一个新的一致状态。事务的原子性保证其一致性
3. 隔离性(insulation),主要在并发时,各个事务之间互不影响。并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
4. 持久性(Duration),事务一旦提交,数据就永久的保存在数据库,它对于系统的影响是永久性的。
二,并发带来的数据安全问题。
1 脏读:一个事务读取到另一个事务未提交的数据,显然该未提交事务可能发生错误而回滚没有保存进数据库,那么读到的数据就是错误的数据。
2.第一类更新丢失:开启一个事务,读取到一行数据,另一个事务也读到同一行数据。后一个事务提交事务保存到数据库后第一个事务更新时发生异常而回滚导致后一个事务的更新丢失
3 第二类更新丢失:一个事务从数据库得到一行数据保存在内存中,这时另一个事务开发也读到同一行一样的数据,另一个事务更改了事务并提交保存到数据库。这时第一个事务依然是最开始的数据(没有重新去数据库读取)进行修改提交导致另一个事务提交的信息丢失。
4 不可重复读:一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。
5 幻读: A事务读取B事务提交的新增数据,这时A事务将出现幻象读的问题
注:幻象读和不可重复读是 两个容易混淆的概念,前者是指读到了其它已经提交事务的新增数据,而后者是指读到了已经提交事务的更改数据(更改或删除)
三、数据库事务隔离级别
为了解决数据库事务并发运行时的各种问题数据库系统提供四种事务隔离级别:
1. Serializable 串行化
2. Repeatable Read 可重复读
3. Read Commited 可读已提交
4. Read Uncommited 可读未提交
隔离级别与并发性能的关系:
四种隔离机制的个人理解:
1,Read Uncommited 可读未提交:字面意思可以读取未提交的事务。在并发操作时,一个事务可以读取另一个事务对数据的改动。可能发生脏读,第二类更新丢失,幻读,不可重复读,不会发生第一类更新丢失。
2 Read Commited 可读已提交:两个事务之间已经提交的可以互读。可能发生第二类更新丢失,幻读,不可重复读,不会发生脏读,第一类更新丢失(根据其发生的原因)。
3 Repeatable Read 可重复读:在事务执行期间会锁定该事务以任何方式引用的所有行。如果在同一个事务中发出同一个SELECT语句两次或更多次,那么产生的结果数据集总是相同的。因此,使用可重复读隔离级别的事务可以多次检索同一行集,并对它们执行任意操作,直到提交或回滚操作终止该事务。脏读、不可重复的读、第二类更新丢失现象都不会发生,但是幻读会发生。
1. Serializable 串行化:Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。
四 事务隔离机制使用:
MySQL的默认事务隔离级别是:Repeatable Read
SQL Server的默认事务隔离级别是:Read Commited
Oracle数据库支持Read Commited 和 Serializable这两种事务隔离级别。Oracle 默认使用的是Read Commited
应用时设置数据库的隔离级别:
1.在Hibernate的配置文件中可以显示的配置数据库事务隔离级别。每一个隔离级别用一个整数表示:
8 - Serializable 串行化
4 - Repeatable Read 可重复读
2 - Read Commited 可读已提交
1 - Read Uncommited 可读未提交
在hibernate.cfg.xml文件中加入<property name="hibernate.connection.isolation">2</property>
2.在spring与hibernate整合时,
1.在spring的配置文件的 SessionFactory bean中添加hibernate.connection.isolation属性
2.使用注解@Transactional(isolation=Isolation.REPEATABLE_READ),
isolation:设隔离级别。默认为底层数据库的隔离级别
noRollbackFor:指定遇到特定的异常不强制回滚.@Transactional(notRollbackFor=RunTimeException.class)运行异常不回滚(rollbackFor相反)
noRollbackForClassName:指定遇到多个特定的异常不强制回滚。RollbackForClassName相反
propagation:指定事务的传播行为、修饰bean对象表示对该对象起作用,修饰bean方法只对该方法有效
1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
五 数据库悲观锁和乐观锁
http://www.cnblogs.com/wang-meng/p/5506943.html
参考资料:http://blog.csdn.net/fg100emil/article/details/2927098
http://www.cnblogs.com/jerryxing/archive/2012/04/24/2468999.html
小白第一次写博客,望各位大神指出错误。学习改进