架构设计事务篇之Mysql事务原理

avatar

概述

事务是一组读写操作,这些操作被当作一个独立的工作单元被执行,这些操作的执行结果要么全部成功,要么全部失败,不允许部分成功、部分失败的情况出现。
在数据库中,事务的作用是为了保障数据的一致性,即:操作结果和期望的结果一致,它有四个特性:原子性、一致性、隔离性、持久性。

实列

事务最典型的一个例子是转账,假设我们有一个账户表,表中有两条记录,一条是A账户的记录其余额为100,另一条是B账户的记录其余额为50。
这时,A账户发起了一笔转账到B账户的请求,其金额为50;此时该转账操作便是一个事务,它包含两个写操作,一个是A账户扣减50,另一个是B账户增加50;
这两个操作是不可分割的,不能出现只执行其中一个而不执行另一个,也不能出现其中一个失败另一个成功,否则执行结果就和我们期望的结果不一致。
比如,A执行成功,B执行失败,那么结果是A账户余额为:50,B账户余额还是:50,这样就和我们业务上期望的结果A为:50、B为:100不一致了。
两个操作对应的数据库Sql语句如下:


//扣减A账户金额
update account set balance=balance-50 where id="A";
//增加B账户金额
update account set balance=balance+50 where id="B";

问题

因此,为了保障事务的一致性,我们首先要保重的是事务中的操作要么都成功要么都失败不能出现其它情况,而且当其中某些操作失败时,该事务中其它成功的操作需要被撤销使数据恢复到事务执行前的状态,
这便是我们碰到的第一个问题:需要保证事务的原子性。
其次,因为数据操作都是先从磁盘加载到内存,然后在内存进行数据更新,最后同步到磁盘,这就引发了操作执行后数据持久性的问题,即:如何保证事务成功后重启数据库后数据状态还是期望的状态。
最后,因为现代处理器的架构都是多核架构,在支持多个事务并行处理的情况下,如何保证事务之间不相互影响,这便是事务之间隔离性的问题,比如说:同一时刻有两个事务给B账户转账50,如果两个事务在执行过程中获取的账户金额都是50,那么最后的结果便是100,而不是150,这就和期望的结果不一致了;

所以,为了保证数据的一致性,我们需要事务保证其操作执行的原子性和隔离性以及操作结果即数据的持久性。

方案

下面我们以最常用的数据库Mysql为例,讲解一下它是通过什么方式保证事务的原子性、隔离性以及持久性的,从而实现数据的一致性。

原子性

原子性所要解决的关键问题是事务执行失败时,已经执行成功的操作如何撤销或者说如何将已经被更改的数据恢复到该事务开始执行前的状态。
Mysql使用的是undo日志,事务开始后,如果要修改某一条记录,Mysql会先将该记录的原始值保存在undo日志中并同步到磁盘,接着才是修改记录,最后提交事务。

比如,我们只执行下面这条Sql语句:

update account set balance=balance-50 where id="A";

那么其事务实现过程大致如下:

1、开始事务A
2、将balance原始值100存储到undo日志中
3、将balance修改为50
4、提交事务

在上面的事务的执行过程中,如果事务执行到第三步出现了异常,那么可以通过undo日志恢复内存中的数据,如果在这之前出现异常什么都不需要做因为日志数据和原始数据是一致的。

持久性

持久性所面临的问题是如何将内存中的数据高效地同步到磁盘,如上面的例子最简单的方法就是在第三步后第四步前,将balance写入磁盘,如下:

1、开始事务A
2、将balance原始值100存储到undo日志中
3、将balance修改为50
4、将balance数据写入磁盘
5、提交事务

但是,如果存在多条变更的数据会因磁盘寻址耗时导致数据库处理事务的性能变低,所以Mysql采用redo日志来顺序记录变更的数据,这样减少了不必要的寻址。
等到,事务提交后,Mysql会使异步将redo中的数据线程

隔离性

隔离性所面临的问题是一个事务在执行的过程中是否允许另一个事务读取它正在修改的数据,如果不允许那么就得让事务串行化,这是最高的隔离级别,如果允许那么又有三种不同的隔离级别:读未提交、读已提交、可重复读。

读未提交:一个事务可以读取另一个事务未提交的数据,这种不采取任何隔离措施的策略会导致脏读、幻读、不可重读等问题,而且对数据一致性没有任何保障。

读已提交:一个事务可以读取另一个事务已经提交的数据,它避免了脏读,但还存在幻读、不可重复读的问题。

可重复读:同个事务多次读取相同的数据放回的结果是一样的,Mysql的可重复读可以解决脏读、幻读、不可重读的问题。

那什么情况下会发生脏读、幻读、不可重读呢?

脏读发生在一个事务A读取另一个事务B未提交的数据时,如果B最后因为失败回滚,那么A读取的数据就是无效的。

幻读发生在一个事务向数据库插入某条数据ID为X的记录是,它先select没有发现该记录,然后准备插入此时发现数据库已经存在该条记录,这条记录是另一个事务在其select之后提交的。

不可重复读发生在一条记录被并发修改,这样导致会导致某个事务多次读取的数据结果不一样。

扩展阅读

架构设计思维篇之结构

架构设计思维篇之概念

架构设计容错篇之重试

架构设计容错篇之熔断

架构设计容错篇之限流

架构设计事务篇之Mysql事务原理

架构设计事务篇之CAP定理

架构设计事务篇之分布式事务

架构设计消息篇之消息丢失

架构设计消息篇之保证消息顺序性

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

推荐阅读更多精彩内容