一般的数据库,都包括以下四种隔离级别:
读未提交(Read Uncommitted)
在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,
所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。
读提交(Read Committed)
读提交,顾名思义,就是只能读到已经提交了的内容。
这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。
这种隔离级别能够有效的避免脏读,但除非在查询中显示的加锁,
不然,普通的查询是不会加锁的。
那为什么“读提交”同“读未提交”一样,都没有查询加锁,但是却能够避免脏读呢?、
这就要说道另一个机制“快照(snapshot)”,
而这种既能保证一致性又不加锁的读也被称为“快照读(Snapshot Read)”
假设没有“快照读”,那么当一个更新的事务没有提交时,
另一个对更新数据进行查询的事务会因为无法查询而被阻塞,
这种情况下,并发能力就相当的差。
而“快照读”就可以完成高并发的查询,不过,
“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。
可重复读(Repeated Read)
可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,
自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。
在这个级别下,普通的查询同样是使用的“快照读”,
但是,和“读提交”不同的是,当事务启动时,就不允许进行“修改操作(Update)”了,
而“不可重复读”恰恰是因为两次读取之间进行了数据的修改,
因此,“可重复读”能够有效的避免“不可重复读”,但却避免不了“幻读”,
因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。
序列化读(Serializable)
这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。
这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,
但是执行效率奇差,性能开销也最大,所以基本没人会用。
总结一下
为什么会出现“脏读”?因为没有“select”操作没有规矩。
为什么会出现“不可重复读”?因为“update”操作没有规矩。
为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。
“读未提(Read Uncommitted)”能预防啥?啥都预防不了。
“读提交(Read Committed)”能预防啥?
使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。
“可重复读(Repeated Red)”能预防啥?
使用“快照读(Snapshot Read)”,锁住被读取记录,
避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。
“串行化(Serializable)”能预防啥?
排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道