- 脏读(读取未提交的数据)
A事务读取B事务还未提交的数据,此时B事务因某些原因回滚,那么A读到的这个数据就是脏读。
以转账为例
1 | 开始事务 | |
2 | 查询余额1000元 | |
3 | 取款200元,余额变为800元 | |
4 | 开始事务 | |
5 | 查询余额800元(脏读) | |
6 | 存款1000,余额变为1800 | |
7 | 取款出错,回滚,余额变为1000 | |
8 | 提交事务 | |
备注 | 正常逻辑,余额应该是2000元。这里产生了脏读 |
- 不可重复度(多次读取,数据不一样)
是指一个事务内2次读取同一个数据的值不一样。以转账为例:A事务读取余额1000元,B事务存款1000,然后A事务再次读取余额为2000元。
1 | 开启事务 | |
2 | 第一次查询余额1000元 | |
3 | 开启事务 | |
4 | 存款1000元,余额变为2000元。 | |
5 | 提交事务 | |
6 | 第二次查询余额2000元 | |
备注 | 通常情况下2次查询余额应该一样,但是有时候要看具体业务 |
解决:使用行级锁,锁定当前记录,其它事务无法更改。针对update操作
- 幻读(多次读取,数据总量不一样)
指一个事务内2次统计数据总量,值不一样。
1 | 开启事务 | |
2 | 第一次查询数据总量为1000条 | |
3 | 开启事务 | |
4 | 插入1000条数据 | |
5 | 提交事务 | |
6 | 第二次查询数据总量为2000条 |
解决:使用表级锁,针对insert操作。不过,这个应该没人用吧,需要锁表的业务几乎没有,有也要选中其它方式去解决,否则严重影响性能。
针对上面的并发问题,数据库支持对应的事务隔离级别,级别从低到高分别为:Read uncommitted、Read committed、Repeatable read、Serializable
事务级别 | 脏读 | 不可重复读 | 幻读 |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
另外一一个不错的文章:https://www.cnblogs.com/dwxt/p/8807899.html