数据库事务的基本概念
事务的特性 ACID
- 原子性 (Atomicity)
事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生 - 一致性 (Consistency)
如果事务执行之前数据库是一个完整的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整的状态 - 隔离性 (
Isolation
)
多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离 - 持久性 (Durability)
指一个事务一旦被提交,对数据库的影响是永久性的
隔离性
- 脏读
一个事务读取了另一个事务改写但还未提交
的数据,如果这些数据被回滚,则读到的数据是无效的 - 不可重复读
在同一个事务中,多次读取同一个数据返回的结果有所不同;这是由于在查询间隔,被另一个事务修改并提交了;
不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读
则是读取了前一事务提交的数据;
在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据,A和B依次查询就可能不同,A和B就可能打起来了 - 幻读
一个事务读取了几行记录后,另一个事务插入一些数据,幻读就发生了;在后来的查询中,第一个事务就会发现有些原来没有的记录;
幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读
查询的都是同一个数据项,而幻读
针对的是一批数据整体(比如数据的个数)。
隔离级别 Isolation
- READ_UNCOMMITTED (读未提交)
可能导致脏读、不可重复读、幻读
- READ_COMMITTED (读已提交)
可防止脏读,但不可重复读、幻读
仍可能发生 - REPEATABLE_READ (可重复读)
可防止脏读和不可重复读,但是幻读
仍可能发生 - SEPIALIZABLE (串行化)
完全服从ACID的隔离级别,确保不发生脏读、不可重复读、幻读。
这在所有隔离级别中是最慢,成本最高,它是典型的通过完全锁定事务中涉及的数据表来完成的
隔离级别的设置只对当前连接有效
;(对JDBC操作数据库来说,一个Connection对象相当于一个连接,只对该Connection对象设置的隔离级别只对该connection对象有效,与其它连接connection对象无关。)
MySQL 支持上面四种隔离级别,默认隔离级别是:REPEATABLE_READ
(可重复读) ;
Oracle 只支持 SEPIALIZABLE 和 READ_COMMITTED ,默认隔离级别是:READ_COMMITTED
(读已提交);
读未提交 < 读已提交 < 可重复读 < 串行化
传播行为 propagation
解决业务层方法之间的相互调用的问题
-
PROPAGATION_REQUIRED
支持当前事务,如果不存在就新建一个;如果当前存在事务,就加入该事务,该设置是最常用的设置
。 -
PROPAGATION_SUPPORTS
支持当前事务,如果不存在就不使用事务 -
PROPAGATION_MANDATORY
支持当前事务,如果不存在抛出异常 -
PROPAGATION_REQUIRED_NEW
如果有事务存在,挂起当前事务,创建一个新的事务 -
PROPAGATION_NOT_SUPPORTED
以非事务方式运行,如果有事务存在,挂起当前事务 -
PROPAGATION_NEVER
以非事务方式运行,如果有事务存在,抛出异常 -
PROPAGATION_NESTED
如果当前事务存在,则嵌套事务执行