事务、隔离级别和并发一致性问题

前言

大家好,我是fancy呀。

数据库的事务一直以来是数据库最核心的基础知识,熟悉事务知识是深入学习数据库的前提;同时,数据库的事务也是互联网面试最最最常问的知识之一。

本文我们将从以下几个角度深入分析:

事务的四大特性->数据库并发环境下的一致性问题->数据库的隔离级别分别所解决的一致性问题。

话不多说,小伙伴们,上车吧🚙!

事务

什么是事务?

事务是数据库系统里面非常重要的术语。它可以由一行简单的SQL来实现,也可以由一组复杂的SQL来实现。对于MySQL来说,有两种事务实现方式,一种是显式事务,另一种则是隐式事务。显式事务需要我们自己手动使用begin或start transaction开启事务,执行完中间的SQL语句后使用commit提交事务,即手动提交。

InnoDB默认为隐式事务,即自动提交,每一行insert、update、delete的SQL语句操作都默认为一个独立的事务。如果想关闭自动提交,可以set autocommit = 0来实现。

本质上来说,事务其实就是一系列逻辑操作,为了保证这一系列逻辑操作能够被准确、统一、安全地执行,就需要通过规范和技术来实现事务,让事务具备特性。

事务有什么特性?

1.原子性(Atomicity)

一个事务被视为不可分割的最小单元,一个事务的所有操作要么全部提交成功,要么全部失败回滚。当你为一组行为开启事务时,这组行为的全部操作要么同时成功,要么同时失败,不存在某一步行为成功执行而另一步执行失败的场景。一旦某个行为操作失败,那么这组行为里包括执行成功和执行失败的会全部回滚,就像什么事都没发生过一样。

2.隔离性(Isolation)

一个事务所做的修改在最终提交以前,对其它事务是不可见的。

3.一致性(Consistency)

数据库的数据在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。不能存在同一个事务对某一组数据前后两次读取的内容不一致的场景。

4.持久性(Durability)

一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

对于一个事务,想要实现它必须遵循以上ACID四个特性,也就是这四个特性必须全部得到满足才可以称之为一个完整的数据库“事务”。

那么InnoDB如何去实现这四个特性呢?不同的特性其实有不同的实现方式:

并发一致性问题

什么是数据库的并发一致性问题?

并发一致性问题,指的是在并发环境下,因为事务的隔离性很难保证,所以会出现很多并发问题。

数据库的并发一致性问题一共有三种,分别是:

1.脏读(Dirty Read)

指的是事务A读取到了事务B已经修改但是还未提交的数据

假设A和B同时读取一个数据,事务A读取到这个数据的值为10,随后将其值修改为20,按道理,事务A对这个数据的修改在事务未提交之前是不会被其他事务看到的,但是由于数据库的隔离性未能保证,此时事务B也去读取这个数据的值,就会直接读取到事务A修改完之后的值20,那么此时如果事务A进行了数据的回滚,不提交了。那么事务B最终读取到的就是一个过期的值20。

这种情况就称为脏读。

2.不可重复读(Nnrepeatable Read)

指的是在一个事务里面两次读取到的内容不一样。

事务B读取到某个数据S的值为10,随后事务A将S的值修改为20。如果B再次读取这个数据,读取到的值就变为20。此时读取的结果和第一次读取的结果不同,这就是不可重复读。按道理,事务B都还没有提交,所读取到的数据应该是对别的事务不可见的,换句话来说应该是安全的。但是由于并发环境下事务的隔离型未能满足,多个事务在某一个相同时刻对同一个数据进行修改,就会出现这样的并发冲突问题。

3.幻读(Phantom Read)

指的是在一个事务内查询某个数据范围的数据,如果出现了两次查询的结果不一样,就称为“幻读”。

事务A根据条件查询到某个范围的数据[10,20,30,40.50],此时B在这个符合条件的范围内插入新的数据,A再次读取这个范围的数据后,发现该范围多出了一条数据60,此时就发生了“幻读”现象。幻读现象发生的本质,也是由于事务的隔离型未能保证导致的。

所以,MySQL如何解决并发一致性问题?

首先强调一下,MySQL并不等于InnoDB。

InnoDB是MySQL5.5版本之后默认使用的存储引擎。InnoDB使用MVCC可以解决脏读和不可重复读问题。但是,MVCC并不是唯一可以解决并发一致性问题的措施。MVCC本质上是一种乐观锁,通过比较不同事务的版本号的方式来解决问题。可以使用乐观锁,那么一样也可以使用悲观锁。MySQL的其他存储引擎比如Myisam甚至无法使用事务,所以它一般用锁来解决并发一致性问题。

在这里,我先不赘述InnoDB的MVCC和MySQL各种各样的锁,我们放到之后的文章来讲。本篇文章主要强调事务本身☺️。

隔离级别

什么是数据库的隔离级别?

指的是实现了数据库中的安全级别。从对ACID的实现程度上分为四个隔离级别。隔离级别越高的数据库越安全,能解决的并发一致性问题也就越多。

那么数据库有几种隔离级别呢?

1.未提交读(Read Uncommitted)

事务中的修改,即使没有提交,对其它事务也是可见的。该隔离级别会发生脏读、不可重复读、幻读。所以是最差的一个隔离级别。

2.提交读(Read Committed)

一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的,所以该隔离级别解决了脏读问题,也就是说,当你的数据库实现到了提交读这个隔离级别时,脏读现象就不会再发生

3.可重复读(Repeatable Read)

保证在同一个事务中多次读取同一数据的结果是一样的。这是第三个隔离级别,也是InnoDB默认实现的隔离级别

当你的数据库实现到了提交读这个隔离级别时,脏读和不可重复读现象就都不会再发生

4.可串行化(Serializable)

强制事务串行执行,这样多个事务互不干扰,自然而然就不会出现并发一致性问题。

该隔离级别需要加锁实现,因为要使用加锁机制保证同一时间只有一个事务执行。

因为可串行化是串行执行,所以不会有并发问题。这也是最安全的,第四个隔离级别。

总结一下:

读未提交就是一种最差的数据库隔离级别, 说明你这个数据库在多事务的时候非常不安全;

提交读能解决脏读问题;

可重复读能解决不可重复读和脏读问题;

串行化能解决脏读、不可重复读、幻读问题。

为什么InnoDB不默认实现可串行化?

数据库提出了这四种隔离级别分别来解决不同的并发一致性问题。

但是,难道隔离级别越高就越好吗?对于各大编程语言,不仅仅要考虑“安全”,还要考虑“性能”,对于数据库一样如此。

隔离级别越高,就代表着越安全,但是同时性能效率也就越低。你想想,当你的数据库做到了串行化,就意味没有并发问题产生。但是此时你读取的数据身上挂着一把锁,一个数据同一时刻只能被一个事务访问,那么剩下的事务获取不到就只能排队。实际生产环境中往往都是在并发环境中对数据库进行操作,业务高峰的时候甚至会有几万、几十万个事务同时存在,所以串行化往往得不到业务上的满足。这就需要在“安全”和“性能”之间做一个衡量,于是MySQL的InnoDB存储引擎默认实现的隔离级别为“可重复读”,而非可串行化。

总结

事务本质上就是一系列逻辑操作,不同数据库、不同存储引擎对事务的支持强度都是不一样的。比如Mysql数据库InnoDB引擎天然支持事务,而Myisam引擎则不支持事务。

数据库事务只有满足了ACID四大特性,才能安全的被我们执行。如果是在某一个时刻只有一个事务在操作,那么就不会出现并发一致性问题,那么ACID就很容易满足。因为隔离性是可以满足的,我们只要满足了原子性,就可以满足一致性。

但是在多事务的并发环境下,由于事务的隔离性很难满足,就会产生脏读、不可重复读、幻读的并发一致性问题。为了解决这些并发一致性问题,数据库系统规范了四个隔离级别:未提交读、提交读、可重复读、可串行化。

隔离级别越高,并发环境下数据库越安全,但是性能也越低。所以为了权衡安全和性能,InnoDB默认实现的隔离级别是“可重复读”。

那么如何实现可重复读呢?可以使用锁,也可以使用MVCC。

那么下一期,我们就来深入地讲一讲InnoDB的一大利器“MVCC”。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容