脏读就是指当一个事务正在访问数据, 并且对数据进行了修改, 而这种修改还没有提交到数据库中, 这时, 另外一个事务也访问这个数据, 然后使用了这个数据.
时间 & nbsp; | 取款事务 A | 转账事务 B |
T1 | 开始事务 & nbsp; |
|
T2 |
| 开始事务 & nbsp; |
T3 | 查询账户余额为 1000 元 & nbsp; |
|
T4 | 取出 100 元把余额改为 900 元 & nbsp; |
|
T5 |
| 查询账户余额为 900 元(脏读) |
T6 | 回滚事务 & nbsp; |
|
T7 | 余额恢复为 1000 元 |
|
(3) 不可重复读 (两次读的不一致)
是指在一个事务内, 多次读同一数据, 在这个事务还没有结束时, 另外一个事务也访问该同一数据. 那么, 在第一个事务中的两次读数据之间, 由于第二个事务的修改, 那么第一个事务两次读到的的数据可能是不一样的. 这样就发生了在一个事务内两次读到的数据是不一样的, 因此称为是不可重复读.
时间 & nbsp; | 取款事务 A | 转账事务 B |
T1 |
| 开始事务 & nbsp; |
T2 | 开始事务 & nbsp; |
|
T3 |
| 查询账户余额为 1000 元 & nbsp; |
T4 | 查询账户余额为 1000 元 & nbsp; |
|
T5 | 取出 100 元把余额改为 900 元 & nbsp; |
|
T6 | 提交事务 |
|
T7 |
| 查询账户余额为 900 元(不可重复读) |
(4) 第二类更新丢失 (覆盖丢失)
第二类更新丢失实在实际应用中经常遇到的并发问题, 他和不可重复读本质上是同一类并发问题, 通常他被看做不可重复读的特例: 当多个事务查询同样的记录然后各自基于最初的查询结果更新该行时, 会造成第二类丢失更新. 因为每个事务都不知道不知道其他事务的存在, 最后一个事务对记录做的修改将覆盖其他事务对该记录做的已提交的更新.
时间 & nbsp; | 取款事务 A | 转账事务 B |
T1 |
| 开始事务 & nbsp; |
T2 | 开始事务 & nbsp; |
|
T3 |
| 查询账户余额为 1000 元 & nbsp; |
T4 | 查询账户余额为 1000 元 & nbsp; |
|
T5 | 取出 100 元把余额改为 900 元 & nbsp; |
|
T6 | 提交事务 |
|
T7 |
| 转出 100 元把余额改为 900 元(更新丢失) |
(5) 幻读
是指当事务不是独立执行时发生的一种现象, 例如第一个事务对一个表中的数据进行了修改, 这种修改涉及到表中的全部数据行. 同时, 第二个事务也修改这个表中的数据, 这种修改是向表中插入一行新数据. 那么, 以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行, 就好象发生了幻觉一样.
时间 & nbsp; | 账户更新事务 A | 账户新增事务 B |
T1 | 开始事务 & nbsp; |
|
T2 |
| 开始事务 & nbsp; |
T3 | 把所有账户的余额清 0 |
|
T4 |
| 插入一个新账户,设置余额为 100 |
T5 |
| 提交事务 |
T6 | 获取账户余额,发现还有一个没清 0(幻读) |
|
2, 数据库的四种隔离级别
(1) 读未提交 (READ UNCOMMITTED)
一个事务的修改, 即使没有提交, 对其他事务也都是可见的. 这种隔离级别, 一般在读数据时不会检查或使用任何锁. 因此, 会出现脏读问题.
(2) 读已提交 (READ COMMITTED)
只读取提交的数据并等待其他事务释放排他锁. 这种隔离级别, 读数据的共享锁在读操作完成后立即释放, 因此会出现不可重复读问题.
(3) 可重复读 (REPEATABLE READ)
像读已提交级别那样读数据, 但会保持共享锁直到事务结束. 这种隔离级别, 虽然保持行锁到事务提交结束, 但是不能阻碍其他事务插入数据, 所以存在幻读问题.
(4) 可串行化 (SERIALIZABLE)
工作方式类似于可重复读. 但它不仅会锁定受影响的数据, 还会锁定这个范围. 这就阻止了新数据插入查询所涉及的范围.
下表是是各隔离级别对各种异常的控制能力:
| 第一类更新丢失可能性 | 脏读可能性 | 不可重复读可能性 | 第二类丢失更新可能性 | 幻读可能性 |
读未提交 | N | Y | Y | Y | Y |
读已提交 | N | N | Y | Y | Y |
可重复读 | N | N | N | N | Y |
串行读 | N | N | N | N | N
|
来源: http://www.bubuko.com/infodetail-2945547.html