数据并发的问题
一个数据库可能拥有多个访问客户端,这些客户端都可以并发方式访问数据库。数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。
并发出现的数据问题:脏读,不可重复读,幻读
脏读:A事务读取B事务没有提交的更新数据
脏读场景:
时间
|
转账事务A
|
取款事务B
|
T1
|
|
开始事务
|
T2
|
开始事务
|
|
T3
|
|
查询账户余额为1000元
|
T4
|
|
取出500元把余额改为500元
|
T5
|
查询账户余额为500元(脏读)
|
|
T6
|
|
撤销事务余额恢复为1000元
|
T7
|
汇入100元把余额改为600元
|
|
T8
|
提交事务
|
|
不可重复读:事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
时间
|
取款事务A
|
转账事务B
|
T1
|
|
开始事务
|
T2
|
开始事务
|
|
T3
|
|
查询账户余额为1000元
|
T4
|
查询账户余额为1000元
|
|
T5
|
|
取出100元把余额改为900元
|
T6
|
|
提交事务
|
T7
|
查询账户余额为900元(和T4读取的不一致)
|
|
幻读:A事务读取B事务提交的新增或删除的数据,这时A事务将出现幻象读的问题。幻象读一般发生在计算统计数据的事务中。
时间
|
统计金额事务A
|
转账事务B
|
T1
|
|
开始事务
|
T2
|
开始事务
|
|
T3
|
统计总存款数为10000元
|
|
T4
|
|
新增一个存款账户,存款为100元
|
T5
|
|
提交事务
|
T6
|
再次统计总存款数为10100元(幻象读)
|
|
数据库的四种隔离级别:Read uncommitted 、Read committed、Repeatable read 、Serializable
Read uncommitted 读未提交
会出现脏读的情况,解决方法:将隔离级别设置为Read committed
Read committed 读提交
当隔离级别设置为Read committed时,避免了脏读,但是可能会造成不可重复读。解决方法:将隔离级别设置为Repeatable read
大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。
Repeatable read 重复读
当隔离级别设置为Repeatable read时,可以避免不可重复读。虽然Repeatable read避免了不可重复读,但还有可能出现幻读。
注:MySQL的默认隔离级别就是Repeatable read。
Serializable 序列化
Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。