innodb 隔离等级

前一段时间参加了一个国内知名公司的面试,被问及对数据库的了解,自感还不错,可谁知在隔离等级这种基本概念的点翻个船,也不是由于彻底不懂,而是原本这里就比较晦涩,加之具体上次看这里的东西时候已通过了一年多,中间一直在作索引相关优化的工做,因此关于隔离等级的概念点的记忆很模糊,致使了面试时候的啪啪打脸,索性最后安全线度过,如今想来,确实有点发挥失常。在这里也劝解你们,有时间跟臭味相同的技术员们聊聊天,面面试,不断回顾一些理论上的知识,而不要一味扎在业务里不出来。毕竟,你们都是要成为一名优秀的程序员啊~。啰嗦的话说到这里,下面进入主题mysql

 

都知道 innodb 引擎是支持事务这一特性的,由于要介绍事务隔离等级,因此简单回顾一下事务的特性 ACID程序员

  • A:Atomicity,原子性,指事务的操做要么所有成功,要么所有失败
  • C:Consistency,一致性,指事务的先后的条件必须保持一致的
  • I:Isolation:隔离性,两个事务之间确保不相互影响,具备彻底隔离特性
  • D:Durability:持久性,事务一旦提交,不会发生丢失回退的现象

 

接下来咱们介绍一下具体是根据什么因素去区分 4 种隔离等级的面试

 

1,未提交读(Read uncommited),会产生赃读,会读到另外一个事务未提交的数据sql

 

start A                                                                            | start B数据库

select * from test; -> 1,2,3                                             | -安全

-                                                                                     | insert into test xx values(4)并发

select * from test; -> 1,2,3,4                                          | -高并发

 

这里看到在事务 B 还未提交的状况下,事务 A 已经能够读到新的数据,违反了事务的隔离性、一致性,这种等级通常在业务场景中不多应用,由于彻底没有事务可言优化

 

2,已提交读(Read commited),会产生不可重复读,会在同一个事务中读到另外一个事务提交的数据索引

 

start A                                                                            | start B

select * from test; -> 1,2,3                                             | -

-                                                                                     | insert into test xx values(4)

select * from test; -> 1,2,3                                             | -

-                                                                                     | commit

select * from test; -> 1,2,3,4                                          | -

 

能够看到 A 事务并没结束,但因为 B 事务已经提交,这边已经能够读到插入的数据,虽然违反了事务的一致性,但相对而言,已经达到不少业务场景的须要,因此如今不少数据库都是采用这个等级

 

3,可重复读(Repeatable read),会产生幻读,会在同一个事务中读到数据后,进行修改但发现数据已经被修改,这个等级也是 innodb 的默认等级。

 

start A                                                                            | start B

select * from test; -> 1,2,3                                             | -

-                                                                                     | insert into test xx values(4)

select * from test; -> 1,2,3                                             | -

-                                                                                     | commit

select * from test; -> 1,2,3                                             | -

insert into test xx values(4) 此处报主键重复错误          | -

 

这里看到事务 A 在整个期间,所看到表中的数据没有发生任何改动,但再最后插入的时候却报了主键重复的错误,缘由是由于事务 B 已经成功插入,这就是幻读想一想,明明没有,但却提示我有。这样说来的话也会存在不少问题,但在实际应用场景中,只要使用得当,就能够利用 key-next lock 在第三等级完美实现事务特性,此处先不啰嗦了,你们只有知道这个等级,已经能够确保 mysql 在高并发下清闲的使用了。

 

4,串行读(Serializable),无任何问题,隔离等级这一次已经彻底实现了事务特性,但代价是全部的读写须要获取表级的共享锁、排它锁。没法进行事务之间的并发就注定了这种等级是食之无味的鸡肋了(固然一些安全等级极高的业务场景也是有可能用到的)

 

最后给出一张图总结以上(不少人开始给出图,我我的以为浮躁的人懒得看,不浮躁的人看不懂,因此诸位不浮躁的人,恭喜大家看到这里了)

 

       隔离级别               脏读(Dirty Read)          不可重复读(NonRepeatable Read)     幻读(Phantom Read)
===========================================================================================

未提交读(Read uncommitted)        可能                            可能                       可能

已提交读(Read committed)          不可能                          可能                        可能

可重复读(Repeatable read)          不可能                          不可能                     可能

可串行化(Serializable )                不可能                          不可能                     不可能