MySQL是多线程并发访问的, 所以很容易出现多个线程同时开启事务的情况, 这样就会出现脏读、不可重复读、幻读的情况.
# 脏读
# 定义
一个事务读取了另一个事务未提交的数据
# 场景
用户a要给商户b转账100元购买商品, a开启事务, 执行下面的update语句进行转账工作
update account set money=money-100 where name='a';
update account set money=money+100 where name='b';
如果a不提交事务, 通知b来查询, 由于b的隔离级别较低, 此时读到了a事务中未提交的事务, 发现a已经转账,
于是给a发货, 等b发货后a就将事务回滚, 此时b就会受到损失
# 不可重复读
# 定义
事务中两次查询的结果不一致, 原因是在查询的过程中其他事务做了更新的操作
# 场景
银行做统计报表时, 第一次查询a账户有1000元, 第二次查询a账户有900元,
原因是统计期间a账户取出了100元, 这样导致多次统计报表的结果不一致
# 幻读
# 定义
又称虚读, 和不可重复读有些类似, 事务中两次查询的结果不一致, 原因是在查询过程中其他事务做了插入的操作
# 场景
银行做统计报表时, 统计account表中所有用户的总额时, 此时总共有3个账户, 总金额有3000,
这时新增了一个账户并且存入1000元, 这时银行发现账户总金额变成了4000, 造成了幻读.
为了避免这些情况的发生, 就需要为事务设置隔离级别, 在MySQL中, 事务有4种隔离级别.
# READ UNCOMMITTED(读未提交)
事务中最低级别, 该级别下的事务可以读到另一个事务未提交的事务, 也称为脏读, 无法避免所有读的问题.
# READ COMMITTED(读提交)
可以避免脏读, 但是不能避免不可重复读和幻读
# REPEATABLE READ(可重复读)
MySQL默认的事务隔离级别, 可避免脏读和不可重复读
# SERIALIZABLE(可串行化)
事务的最高隔离级别, 可避免脏读/不可重复读/幻读
如果一个事务隔离级别是可串行化, 它在每个读的数据行上加上锁,
在这个事务提交之前, 其他线程只能等到当前操作完成后才能进行操作