数据库隔离级别
1. 为什么需要数据库事务隔离级别
事务的隔离级别是为为了解决事务并发引起的问题。
生产者消费者模型是典型的解决多线程并发的一种解决方案。在数据库中也存在类似的问题--事务并发。
事务并发,多个用户同时修改数据库中的同一条数据。并且事务还涉及到事务回滚(rollback)。
2. 事务并发引起的问题
脏读、不可重复读、幻读、第一类更新丢失、第二类更新丢失
脏读
脏读(dirty read),事务A读取到事务B修改后的数据,由于某些原因事务B回滚,这时候事务A读取到的就是脏数据。
不可重复读
不可重复读(nonrepeatable read),在事务A两次读取数据的过程中,事务B修改了数据,导致事务A两次读取到的数据不一致。
幻读
幻读(phantom read),事务A两次读取范围数据的过程中,事务B增加/删除了数据,导致事务A第二次读取到的数据和第一次不同。
幻读强调数据(元组)的增加/减少,脏读强调单条数据的变化。
第一类更新丢失
第一类更新丢失,事务A在修改修改数据的过程中,事务B更新了数据并提交,事务A因为某种原因回滚,导致事务B更新的数据消失。
第二类更新丢失
第二类更新丢失,事务B在事务A执行的过程中更新了数据,然后事务A也更新了数据,导致事务B更新的数据被覆盖。
第一类更新丢失和第二类更新丢失的描述是我在https://www.zhihu.com/question/458275373这篇文章中了解,应该属于脏读、不可重复读和幻读的扩展。
3. 数据库隔离级别
为了解决(减小)事务并发带来的问题,主流的数据库提出了四种事务隔离级别来应对不同的问题。
事务隔离级别从低到高依次为,读未提交、读已提交、可重复度、串行化。事务隔离级别越高,越能保证数据的完整性和一致性,相应的执行效率也会越低。
读未提交
读未提交(read uncommitted),所有事务都可以看到其他事务未提交的事务执行结果。这种隔离级别下可以防止第一类更新丢失,但是会引起脏读、不可重复读和幻读。
读已提交
读已提交(readcommitted),事务只能读取到已经提交的事务的执行结果。这种隔离级别下可以防止第一类更新丢失和脏读,但不能防止不可重复读和幻读。
oracle、sql server默认使用该隔离级别。
可重复读
可重复读(repeatable read),事务不能读写其他事务正在读写的数据,直到其他事务结束。这种隔离级别可以防止第一类更新丢失、第二类更新丢失、脏读和不可重复读,但是还会出现幻读,幻读是范围内增加/删除数据(一条或多条)。
mysql默认使用该隔离级别。
串行化
串行化(serializable),该隔离级别下时事务串行(同步)执行,事务只能一个一个执行,不能并发。这样就可以解决事务并发带来的问题。(解决问题的根本手段,就是从根本上解决事务并发,不允许并发,哈哈)但是可能会导致超时现象(当数据库访问量大时)。