MYSQL(02)-事务原理

ACID模型

MYSQL传统关系数据库的ACID模型有以下特性

  • Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
  • Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
  • Isolation隔离性. 事务将假定只有它自己在操作数据库,彼此不知晓。
  • Durability持久性.一旦事务完成,就不能返回。

MYSQL-ACID模型的实现原理如下

  • 事务的原子性是通过 undo log 来实现的
  • 事务的持久性性是通过 redo log 来实现的
  • 事务的隔离性是通过 (读写锁+MVCC)来实现的
  • 而事务的终极大 boss 一致性是通过原子性,持久性,隔离性来实现的!!!

下面就逐一介绍其实现原理

原子性(Atomicity)原理

一个事务必须被视为不可分割的最小工作单位,一个事务中的所有操作要么全部成功提交,要么全部失败回滚,对于一个事务来说不可能只执行其中的部分操作,这就是事务的原子性。

数据库是通过回滚操作来实现原子性的。 所谓回滚操作就是当发生错误异常或者显式的执行rollback语句时需要把数据还原到原先的模样,所以这时候就需要用到undo log来进行回滚。undo log 就是用于记录更新或新增操作之前的数据状态,当出现需要回滚的情况时,将原数据刷回到数据库中,从而保证操作的原子性,具体实现方式如下:

上面从银行账户转账到理财账户的操作步骤如下

  • 1.事务开始
  • 2.查询数据
  • 3.进行update操作,balance=balance-400;
  • 4.记录zhangsan(1000)到undo log 日志中,回滚时需要将数据更新回来
  • 5.进行update操作,amount=amount+400;
  • 6.记录amount(0)到undo log日志中,回滚的时候需要将数据刷新回来
  • 7.事务提交/回滚

持久性(Durability)原理

事务一旦提交,其所作做的修改会永久保存到数据库中,此时即使系统崩溃修改的数据也不会丢失。
MySQL的数据存储,表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘IO,然而即使是使用SSD磁盘IO也是非常消耗性能的。 为此,为了提升性能InnoDB提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘数据页的映射,可以当做缓存来使用:

  • 读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取在放入缓冲池;
  • 写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中;

上面这种缓冲池的措施虽然在性能方面带来了质的飞跃,但是它也带来了新的问题,当MySQL系统宕机,断电的时候可能会丢数据!因为我们的数据已经提交了,但此时是在缓冲池里头,还没来得及在磁盘持久化,所以我们急需一种机制需要存一下已提交事务的数据,为恢复数据使用。redo log就派上用场了。

redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后在读取redo log恢复最新数据。

隔离性(Isolation)原理

Mysql 隔离级别有以下四种(级别由低到高):

  • READ UNCOMMITED (读未提交)
  • READ COMMITED (读提交)
  • REPEATABLE READ (可重复读)
  • SERIALIZABLE (串行化)

隔离性是要管理多个并发读写请求的访问顺序。 这种顺序包括串行或者是并行,从隔离性的实现可以看出这是一场数据的可靠性与性能之间的权衡,可靠性性高的,并发性能低(比如 Serializable),可靠性低的,并发性能高(比如 Read Uncommited),不同的隔离级别会有不同的问题

- 脏读 不可重复读 幻读
读未提交
读已提交 ×
不可重复读 × ×
串行化 × × ×
  • 脏读:事务中读取到了其他事务没有提交的数据,主要是读写完全没有加锁造成的
  • 不可重复读:事务中多次读取结果不一致,因为多次读取中间,其他事务修改并提交了数据(主要原因是修改)
  • 幻读:事务中多次范围读取结果不一致,因为多次读取中间,其他事务修改并提交了数据(主要原因是新增/删除)

读未提交(READ UNCOMMITED)

\color{red}{概念}:在该隔离级别下,事务中的修改即使还没提交,对其他事务是可见的。其他事务可以读取其未提交的数据,造成脏读。\color{red}{原理}:因为读不会加任何锁,所以写操作在读的过程中修改数据,所以会造成脏读。好处是可以提升并发处理性能,能做到读写并行。

读提交(READ COMMITTED)

\color{red}{概念}:在该隔离级别下,事务中的修改如果还没提交,对其他事务是不可见的。不会造成脏读,但是多次读取会造成数据不一致的情况,会有不可重复度的问题,例如:一个事务中两次读取,在这中间他事务进行了一个更新并提交,那么两次读取的内容会不一样。\color{red}{原理}:InnoDB在该隔离级别下读取数据不加锁而是使用了MVCC机制(详情如下)

可重复读 (REPEATABLE READ)

Mysql\color{red}{默认}隔离级别。在一个事务内的多次读取的结果是一样的。这种级别下可以避免,脏读,不可重复读等查询问题,Innodb可以解决还可以解决幻读问题。Mysql 有两种机制可以达到这种隔离级别的效果,分别是采用读写锁和MVCC机制来实现。

  • 采用MVCC的实现:使用\color{red}{快照读} 的方式支持并行读写并行内部使用MVCC原理(后面介绍)
  • 采用锁的实现:使用\color{red}{当前读} 对于SELECT... FOR UPDATE ,SELECT ... LOCK IN SHARE MODE 等情况使用的是加锁解决机制(记录锁,间隙锁等实现)

串行化(SERIALIZABLE)

  • 该隔离级别理解起来最简单,实现也最单。在隔离级别下除了不会造成数据不一致问题,没其他优点。

MVCC (多版本控制)

MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制,主要是针对事务中并行普通读取的优化。
InnoDB在实现的 MVCC的时候使用一致性视图来保证RC(读提交),和RR(可重复读)事务隔离级别的实现 ,\color{red}{原理}是事务开启时,对整个库创建快照(read view),是通过每行记录的后面保存两个隐藏的列来实现的。这两个列, 一个保存了行的创建时间,一个保存了行的过期时间, 当然存储的并不是实际的时间值,而是系统版本号。每当修改数据时,版本号加一。当事务读取时,如果数据的当前版本号大于自己的事务,则查询的时候抛弃。从而实现不加锁读进而做到读写并行。MVCC在mysql中的实现依赖的是undo log与read view

  • undo log :undo log 中记录某行数据的多个版本的数据。
  • read view :用来判断当前版本数据的可见性

在不同的隔离级别下,MVCC创建read view历史版本的时机也是不同的

  • 在读提交隔离级别下:视图 read-view的创建是在语句执行的时候创建的
  • 在可重复读隔离级别下:视图 read-view的创建是在事务启动的时候创建的

幻读问题详解

幻读在业务中存在两种情况,快照读,和当前读,MVCC策略能够解决快照读的问题,但是对于当前读则需要使用间隙锁。\color{red}{当前读}是指读取数据库中最新版本的数据,在多个update的时候不能基于快照读。读取历史版本的数据进行更新,会导致数据不一致问题

  • 快照读:当使用普通select * 进行统计的时候,使用MVCC可以保证幻读问题
  • 当前读:当使用select for update 或者 select ... lock in share mode 操作的时候,insert,update,delete等操作都会被阻塞。当前读是通过手动加record lock(记录锁)和gap lock(间隙锁 )来实现的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容

  • 一、事务 1、事务四要素:ACID 对于事务,我之前的理解是很粗糙的,不就是为了保证操作的原子性么?一般订单系统或...
    张伟科阅读 1,308评论 0 5
  • 什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点。 原子性:要不全部成功,要不全部撤销 隔...
    jiangmo阅读 1,087评论 0 3
  • 事务原理: 为了支持事务,Innodb引入了下面几个概念: 一、MYSQL 日志介绍: 1.binlog binl...
    极简架构阅读 1,993评论 4 20
  • 事务(Transaction)是数据库区别于文件系统的重要特性之一。 在文件系统中, 如果正在写文件, 但是操作系...
    好好学习Sun阅读 1,017评论 0 5
  • 去年八月末来到了承医,这个远方。 仅希望2017能遇见最好的自己,等我长成一棵大树,等你赞一声良木。
    黄三岁w阅读 281评论 0 0