在标准的SQL规范中,定义了4个事务隔离级别。
未授权读取也被称作读未提交(Read Uncommitted
),这种隔离级别允许读取未提交的数据,隔离级别最低。
RU
这种隔离级别中,允许脏读
, 但不允许出现丢失更新
。
丢失更新
: 两个事务同时更新统一数据时, 会发生更新丢失。
脏读
: 一个事务读取到另一个事务未提交的修改时, 会产生脏读。如:事务A把一数据从1update
成2,update
成3直到update
成9, 事务B每次select
都能看到事务A的中间值(比如2,3或7),对B来说这些就是脏数据。
授权读取也被称为读已提交(Read Committed
),这种隔离级别只允许读取已经被提交的数据。
RC
这种隔离级别中允许出现不可重复读
, 但不允许脏读
不可重复读
: 同一查询在同一事务中多次进行,由于其他提交事务所做的 修改或删除,每次返回不同的结果集,这就发生非重复读。 如:事务A操作数据1, 要把它update
成9, 事务B第一次select
发现是1, 此时事务A提交了, 事务B再次select
发现变成了9, 这种现象叫做不可重复读
。
它的危害也很明显, 因为B第一次读取的时候是1, 若果要对它进行+1在更新回去, 就会变成2, 但实际上这是不对的。(这里你不能用mysql做实验, 因为mysql不再这个隔离级别, 所以这种情况在mysql中不会发生)
可重复读取(Repeatable Read), 这种隔离级别保证在一个事务中,多次读取到的数据都是和事务开始时是一样的。
RR
这种隔离级别允许出现幻读
,但不允许不可重复读
。
幻读
: 同一查询在同一事务中多次进行,由于其他提交事务所做的 插入 操作,每次返回不同的结果集,此时发生幻像读。在RR
中, 事务B读取到的数据值都是跟事务开始时一致(所以可以重复读), 但若事务A新insert
了一条数据, 事务B是可见的, 因此对于事务B来说,开始时没有这个数据,但是过了一会儿却多出来一条数据(数据不一致了),因此对于事务B来说就很莫名其妙。
MySql就是在RR
隔离级别上的, 但它在此基础上又加了gap
锁, 保证了不会出现幻读
。其实MySql中并没有区分不可重复读
和幻读
,MySql统称为幻读
并且禁止了幻读
现象的出现。
串行化(Serializable)是最严格的事务隔离级别,它要求所有的事务都被串行执行。