MySQL定义了四种隔离级别:
包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容-RU):
该级别,所有事务都可以读取到其他事务未提交的数据变化,这种读取其他会话还没提交的事务,叫做脏读现象。所以这种级别很少用到实际应用中,性能会比其他级别强一些。
Read Committed(读取提交内容-RC):
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读-RR):
MySQL默认隔离级别,在一个事务中,直到事务结束前,确保同一事务的多个实例在并发读取数据时,会看到同样的数据行,并一直不会发生变化,避免了脏读、不可重复读现象。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化-S):
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,避免了前面说的幻读现象,简单来说,它会在读取的每一行数据上都加锁,所以可能会导致大量的超时和锁争用问题。
带来的问题:
这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。
- 1.更新丢失
当两个事务选择同一行,然后更新数据,由于每个事务都不知道其他事务的存在,就会发生丢失更新的问题,同时对同一行数据进行修改,后commit的结果将会覆盖掉先commit的结果。
- 2.脏读(Drity Read)
一个事务正在对一条记录做修改,在这个事务提交之前,别的事务读取到了这个事务修改之后的数据,也就是说,一个事务读取到了其他事务还没有提交的数据,就叫做脏读。
- 3.不可重复读(Non-repeatable read)
在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
- 4.幻读(Phantom Read)
一个事务中,读取到了其他事务新增的数据,仿佛出现了幻象。(幻读与不可重复读类似,不可重复读是读到了其他事务update/delete的结果,幻读是读到了其他事务insert的结果)
隔离级别表:隔离级别 读数据一致性 脏读 不可重复读 幻读 未提交读(Read Uncommitted) 最低级别,只保证不读取物理上损坏的数据 有 有 有 已提交读( Read Committed) 语句级 无 有 有 可重复读( Repeatable Read) 事务级 无 无 有 可串行化( Serializable) 最高级别,事务级 无 无 无
隔离级别 | 读数据一致性 | 脏读 | 不可重复读 | 幻读 |
未提交读(Read Uncommitted) | 最低级别,只保证不读取物理上损坏的数据 | 有 | 有 | 有 |
已提交读( Read Committed) | 语句级 | 无 | 有 | 有 |
可重复读( Repeatable Read) | 事务级 | 无 | 无 | 有 |
可串行化( Serializable) | 最高级别,事务级 | 无 | 无 | 无 |
DDL语句通常不受事务控制
查看当前数据库的隔离级别: