面试题之数据库事务隔离级别

一、简介

为了解决脏读、不可重复读、幻读,数据库提供了事务隔离级别的概念,可以最大程度地避免以上三种情况的发生。

根据隔离程度从低到高分为:

  • Read Uncommitted(读未提交);
  • Read Committed(读已提交);
  • Repeatable Read(可重复读);
  • Serializable(串行化);

二、详解

下面对各个隔离级别做一个简介:

  • Read Uncommitted(读未提交):最低的隔离级别,但是并发性能最高,指的是一个事务可以读取到另外一个事务并未提交的数据。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据(写操作加写锁,读操作不加锁)。读未提交会出现脏读、不可重复读、幻读。
  •  
  • Read Committed(读已提交):指的是一个事务的更新操作在未提交之前,另外一个事务是读取不到同一数据更新后的结果,这就避免了脏读。读已提交会锁定当前正在读取的行的数据( 写操作加写锁,读操作加读锁)。读已提交避免了脏读,但是会出现不可重复读、幻读问题。
  •  
  • Repeatable Read(可重复读):mysql的默认的隔离级别,指的是在一个事务内,对相同条件的数据读取结果是相同的,不管其他事务有没有对其进行更新,也不管更新是否已经提交到数据库。可重复读会锁定读取到的所有行直到事务结束,其他事务的更新操作只能等到事务结束之后才能进行。可重复读避免了脏读、不可重复读,但是会出现幻读问题。
  •  
  • Serializable(串行化):最高的隔离级别,当然并发性能最低。指的是所有的事务操作依次顺序执行,事务只能一个接着一个执行,不能并发执行。可序列化对表进行加锁,可以有效避免脏读、不可重复读、幻读问题,但是效率比较低,通常会用其他并发级别加上相应的并发锁机制来取代它。

注意:在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

三、总结

下面通过一张表格展示各个隔离级别对脏读、不可重复读、幻读问题的处理:

事务隔离级别

脏读

不可重复读

幻读

Read Uncommitted(读未提交)

可能会出现

可能会出现

可能会出现

Read Committed(读已提交)

不会出现

可能会出现

可能会出现

Repeatable Read(可重复读)

不会出现

不会出现

可能会出现

Serializable(串行化)

不会出现

不会出现

不会出现

  • 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大(事务的隔离级别和数据库并发性是成反比的,隔离级别越高,并发性越低)。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
  •  
  • 不可重复读和读提交的区别:
  • 不可重复读:读操作会锁定读取到的所有行直到事务结束,可重复读的锁粒度更大;
  • 读提交:读操作是加锁到本次读操作结束,读提交的锁粒度相对较小;
发布了197 篇原创文章 · 获赞 86 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/103796730
今日推荐