数据库事务无非就两种:读取事物(select)、修改事物(update,insert)。
在没有事物隔离控制的时候,多个事物在同一时刻对同一(数据的操作可能就会影响到最终期望的结果,通常有四种情况:
(1) 两个更新事物同时修改一条数据时,很显然这种情况是最严重的了,程序中无论如何也不能出现这种情况,因为它会造成更新的丢失!通俗的讲,我更新时,你也更新这不就出问题了吗,不行!
(2) 一个更新事物更新一条数据时,另一个数据读取了还没提交的更新,这种情况下会出现读取到脏数据。通俗的讲就是,你在我更新的时候读取,我还没提交你就读,你读到了脏数据!
(3) 一个读取事物读取一条数据时另一个更新事物修改了这条数据,这时就会出现不可重现的读取。通俗的讲,我在读数据,你修改了,我读了不一样的数据。
(4)一个读取事物读取时,另一个插入事物(注意此处时插入,(3)中是更新同一条数椐,自己体会)插入了一条新数据,这样就可能多读出一条数据,出现幻读。通俗的讲,我读取数据的时侯你插入新数据了,怪不得我多读了一条呢。
以上四种情况描述完毕,相信大家也发现规律了,前三种是对同一条数据的并发操作,对程序的结果可能产生致命影响,尤其是金融等实时性,准确性要求极高的系统,绝不容许这三中情况的出现,相比第四种情况不会影响数据的真实性,在很多情况下是允许的,如社交论坛等实时性要求不高的系统!
综上四个情况,我们可以大致这样简单的理解(最初说的两种事物的自由组合2*2=4):
A) 修改时允许修改(丢失更新)
B) 修改时允许读取(脏读)
C) 读取时允许修改(不可重复读)
D) 读取时允许插入(幻读)
从上到下问题越来越不严重,但所需的性能开销却越大。因为不同的系统允许不同级别的情况,所以就出现了事务隔离这么一个东东,来允许我们设定数据库的并发行为。
其中
1)读取未提交, 这个级别就是一个事物更新的时候不允许更新,但允许读取,说以不会出现丢失更新,单会出现脏读。隔离级别最低。
2)读取已提交数据,就是一个事物更新的时候不允许读取,必须等到更新事物提交后才能读取,不会出现脏读,但可能出现不可重复度。隔离级别次低。
以上两种级别是针对更新事物的限制,在读取事物进行时,是不会有任何限制的。所以会出现不可重复读(读取时,有更新),和幻读(读取时,插入)。
3)可重现的读取,就是一个事物读取时,不允许更新,但允许插入。不会出现不可重复读,但会出现幻读。
4)序列化(大招),只要有事物进行,其他事物必须等着该事务执行完,所以不会出现任何并发问题。
以上两个事物会限制读取事物的,所以隔离级别较高,但性能开销不容小觑。