数据库的隔离级别可以分为四种类型:
read-commit
脏读 | 不可重复读 | 幻读 | |
uncommitted-read | 会 | 会 | 会 |
committed-read | 不会 | 会 | 会 |
repeatable-read | 不会 | 不会 | 会 |
serializable | 不会 | 不会 | 不会 |
mysql 默认隔离级别为repeatable-read
uncommitted-read情况下模拟脏读,不可重复读,幻读的发生情况:
开启一个事务a,随之一个新的事务b,b事务插入一条数据,此时无论b事务是否提交,a事务都可以读到b事务新插入的一条数据。若b事务回滚,造成a事务的脏读
开启一个事务a,事务a查到一批数据,随之开启一个新的事务b,b事务插入一条数据,提交事务。再次查询事务a,事务a又会多一条数据,这样造成事务a在同一事务中两次读取内容都不相同,构成幻读
开启一个事务a,a事务按照一条条件查询一批记录,此时另外一个事务b更新了其中某条记录,此时事务a按照相同条件查出来的结果与第一次查出来的结果不一致,构成不可重复读
不可重读读和幻读的区别:从表象上看,其表现类似,都是在同一事务中获取到不同的结果。但是其控制方式来看有区别。不可重复读重点在与delete update操作,幻读重点在与insert操作
避免不可重复读:不可重复读可以通过对查询条件加锁来控制,当我查询的时候,给影响的数据加锁,别的事务不可以对其操作,可以避免不可重复读实现重复读。
避免幻读:如果想避免幻读,需要用serializable的隔离级别。读用读锁,写用写锁,读锁写锁互斥。
ps:
如果想保证数据的一致性,把数据库的隔离级别设置为最高的隔离级别serializable。这样又会引起另外的问题,就是严重影响数据库的并发能力,那么如何避免这种情况呢?
这就需要我们以编程方式去控制,设置数据库的最高隔离级别相当于是使用了悲观锁。此时我们既想利用数据库的高并发,高性能,就需要理解乐观锁的概念。乐观锁的实现方式?(基于数据库实现,基于缓存实现,基于zookeeper实现。。。。)