不同的隔离级别会造成三种问题,脏读、不可重复读、幻读。以下讨论是在不使用mvcc多版本控制的情形下产生这三种问题的原因的理解。
一开始我总是难以理解这三种问题如何会发生(特别是脏读),后来想清楚以后觉得最重要的点在于我们思考这个问题的时候要想到一点:所谓的对数据库数据进行修改或者读取操作的互斥的问题,其本质是在修改或者读取之前加锁才会让修改或者读取看起来是互斥的,其实只有锁才会互斥;不加锁的读取或者修改数据的事物(哪怕只有一方加了锁)也是可以同一时间读取和修改同一条数据的。
脏读,就是一个事物T1读到了事物T2还没提交的数据。
如何会造成脏读:如果T1事物在读取数据的时候没有加锁(读锁),T2事物在修改数据的时候不管有没有加锁(写锁);这时候在T1读取期间不排斥其他事物的读或者写,T2仍然可以修改数据,并且在T2还没提交之前,T1也能够读到T2修改的但没有提交的数据。如果T1在读取期间加了读锁,在T1读取期间是不允许T2(如果T2对数据的修改需要加锁的话)进行修改的,也就不存在读到修改但未提交的数据的问题。
不可重复读,就是一个事物T1在事物里面执行了两次同样的查询操作比如where name='xiaoming',每次查询的时候查询完了就立即把读锁释放,所以在两次查询期间有可能会被另一个事物T2加写锁修改后提交,所以T1在第二次查询的时候有可能查询到不一样的数据。
可重复读,事物T1进行了两次读操作,第一次读的时候加了读锁并且一直等到事物提交才释放,所以在事物期间不管读几次因为加了读锁,别的事物无法加写锁修改,所以可以保证可重复度。
串行读,事物T1在读的时候加表读锁,所以在事物期间不会有另外的事物插入的情况,所以不会发生幻读。