欢迎关注专栏:Java架构技术进阶。里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦。

照例,我们先来一个场景~面试官:"知道事务的四大特性么?"

你:"懂,ACID嘛,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)!"

面试官:“你们是用mysql数据库吧,能简单说说innodb中怎样实现这四大特性的么?”

你:"我只知道隔离性是怎样做的balabala~~"

面试官:"还是回去等通知吧~"

OK,回到正题。说到事务的四大特性原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),懂的人很多。但是略微涉及细节一点,这四大特性在数据库中的实现原理是怎样样的?那就没有几个人能够答得上来了。因而,我们这篇文章着重探讨一下四大特性在Mysql中的实现原理。

正文

我们以从A账户转账50元到B账户为例进行说明一下ACID,四大特性。

原子性

根据定义,原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做。即要么转账成功,要么转账失败,是不存在中间的状态!

假如无法保证原子性会怎样样?

OK,就会出现数据不一致的情形,A账户减去50元,而B账户添加50元操作失败。系统将无故丢失50元~

隔离性

根据定义,隔离性是指多个事务并发执行的时候,事务内部的操作与其余事务是隔离的,并发执行的各个事务之间不能互相干扰。

假如无法保证隔离性会怎样样?

OK,假设A账户有200元,B账户0元。A账户往B账户转账两次,金额为50元,分别在两个事务中执行。假如无法保证隔离性,会出现下面的情形

如图所示,假如不保证隔离性,A扣款两次,而B只加款一次,凭空消失了50元,仍然出现了数据不一致的情形!

ps:可能有细心的读者已经发现了,mysql中是依靠锁来处理隔离性问题。嗯,我们后面来说明。

持久性

根据定义,持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其余操作或者故障不应该对其有任何影响。

假如无法保证持久性会怎样样?

在Mysql中,为理解决CPU和磁盘速度不一致问题,Mysql是将磁盘上的数据加载到内存,对内存进行操作,而后再回写磁盘。好,假设此时宕机了,在内存中修改的数据一律丢失了,持久性就无法保证。

设想一下,系统提醒你转账成功。但是你发现金额没有发生任何改变,此时数据出现了不合法的数据状态,我们将这种状态认为是数据不一致的情形。

一致性

根据定义,一致性是指事务执行前后,数据处于一种合法的状态,这种状态是语义上的而不是语法上的。

那什么是合法的数据状态呢?

oK,这个状态是满足预约的束缚就叫做合法的状态,再浅显一点,这状态是由你自己来定义的。满足这个状态,数据就是一致的,不满足这个状态,数据就是不一致的!

假如无法保证一致性会怎样样?

例一:A账户有200元,转账300元出去,此时A账户余额为-100元。你自然就发现了此时数据是不一致的,为什么呢?由于你定义了一个状态,余额这列必需大于0。

例二:A账户200元,转账50元给B账户,A账户的钱扣了,但是B账户由于各种意外,余额并没有添加。你也知道此时数据是不一致的,为什么呢?由于你定义了一个状态,要求A+B的余额必需不变。

实战解答

问题一:Mysql怎样保证一致性的?

OK,这个问题分为两个层面来说。

从数据库层面,数据库通过原子性、隔离性、持久性来保证一致性。也就是说ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段,是为了保证一致性,数据库提供的手段。数据库必需要实现AID三大特性,才有可能实现一致性。例如,原子性无法保证,显然一致性也无法保证。

但是,假如你在事务里成心写出违背束缚的代码,一致性还是无法保证的。例如,你在转账的例子中,你的代码里成心不给B账户加钱,那一致性还是无法保证。因而,还必需从应用层角度考虑。

从应用层面,通过代码判断数据库数据能否有效,而后决定回滚还是提交数据!

问题二: Mysql怎样保证原子性的?

OK,是利用Innodb的undo log。

undo log名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的sql语句,他需要记录你要回滚的相应日志信息。

例如

1、当你delete一条数据的时候,就需要记录这条数据的信息,回滚的时候,insert这条旧数据

2、当你update一条数据的时候,就需要记录之前的旧值,回滚的时候,根据旧值执行update操作

3、当年insert一条数据的时候,就需要这条记录的主键,回滚的时候,根据主键执行delete操作

undo log记录了这些回滚需要的信息,当事务执行失败或者调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

ps:具体的undo log日志长啥样,这个可以写一篇文章了。而且写出来,看的人也不多,姑且先这么简单的了解吧。

问题三: Mysql怎样保证持久性的?

OK,是利用Innodb的redo log。

正如之前说的,Mysql是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再刷回磁盘上。假如此时忽然宕机,内存中的数据就会丢失。 怎样处理这个问题? 简单啊,事务提交前直接把数据写入磁盘就行啊。 这么做有什么问题?只修改一个页面里的一个字节,就要将整个页面刷入磁盘,太白费资源了。毕竟一个页面16kb大小,你只改其中一点点东西,就要将16kb的内容刷入磁盘,听着也不正当。

毕竟一个事务里的SQL可能牵涉到多个数据页的修改,而这些数据页可能不是相邻的,也就是属于随机IO。显然操作随机IO,速度会比较慢。

于是,决定采用redo log处理上面的问题。当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将redo log中的内容恢复到数据库中,再根据undo log和binlog内容决定回滚数据还是提交数据。

采用redo log的好处? 其实好处就是将redo log进行刷盘比对数据页刷盘效率高,具体体现如下redo log体积小,毕竟只记录了哪一页修改了啥,因而体积小,刷盘快。

redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。

ps:不想具体去谈redo log具体长什么样,由于内容太多了。

问题四: Mysql怎样保证隔离性的?

OK,利用的是锁和MVCC机制。还是拿转账例子来说明,有一个账户表如下

表名t_balance

其中id是主键,user_id为账户名,balance为余额。还是以转账两次为例,如下图所示

至于MVCC,即多版本并发控制(Multi Version Concurrency Control),一个行记录数据有多个版本对快照数据,这些快照数据在undo log中。

假如一个事务读取的行正在做DELELE或者者UPDATE操作,读取操作不会等行上的锁释放,而是读取该行的快照版本。

因为MVCC机制在可重复读(Repeateable Read)和读已提交(Read Commited)的MVCC体现形式不同,就不赘述了。

但是有一点说明一下,在事务隔离级别为读已提交(Read Commited)时,一个事务能够读到另一个事务已经提交的数据,是不满足隔离性的。但是当事务隔离级别为可重复读(Repeateable Read)中,是满足隔离性的。

总结

本文讲了Mysql中事务ACID四大特性的实现原理,希望大家有所收获。

喜欢的朋友可以关注下专栏:Java架构技术进阶。里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦。

假如你对技术提升很感兴趣,欢迎1~5年的工程师可以加入我的Java进阶之路来交流学习:908676731。里面都是同行,有资源共享,还有大量面试题以及解析。欢迎一到五年的工程师加入,正当利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

mysql事务ACID实现原理_一文解析:MySQL事务ACID原理让你面试不再害怕相关推荐

  1. mysql布隆过滤器源码_通过实例解析布隆过滤器工作原理及实例

    布隆过滤器 布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 "一定不存在或者可能存在& ...

  2. cdn搭建原理_一文搞懂CDN加速原理

    二.CDN工作原理 传统访问过程 传统访问过程 由上图可见,用户访问未使用CDN缓存网站的过程为: CDN访问过程 CDN访问过程 通过上图,我们可以了解到,使用了CDN缓存后的网站的访问过程变为: ...

  3. 带你一文解析RCU锁机制原理

    原理 Read Copy Update 读(Read):读者不需要获得任何锁就可访问RCU保护的临界区: 拷贝(Copy):写者在访问临界区时,写者"自己"将先拷贝一个临界区副本, ...

  4. npm mysql 事务_一文解读MySQL事务

    经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?本文就帮大家梳理一下. MySQL 事务 本文所说的 MySQL 事务都是指在 I ...

  5. mysql递归查询所有上下节点_【转】MySQL之Spider存储引擎原理详解

    一.概述 Spider是为MySQL/MariaDB开发的一个特殊引擎,具有内嵌分片功能.MariaDB从10.0.4开始支持Spider.作为MariaDB的一个新的主要特性.Spider的主要功能 ...

  6. mysql 回滚之后抛出异常_在PHP中 开始事务后,程序抛出异常 没有执行commit也没有执行rollback mysql事务会回滚吗?...

    网上有人说开启事务后 sql语句执行错误或程序出错 没有执行rollback的情况下,下一次运行就会自动commit 程序出错不会回滚rollback 但是也有人说抛出异常等 程序如果MySQL存在没 ...

  7. mysql删除分表键_一文看懂 MySQL 分区和分表,提高表增删改查效率

    原标题:一文看懂 MySQL 分区和分表,提高表增删改查效率 作者:冯帅,精通Oracle. MySQL. 擅长异构数据库数据同步及迁移.数据库的设计和调优,对高可用方案有深入研究. MySQL分区和 ...

  8. rocketmq原理_彻底看懂RocketMQ事务实现原理

    面试中经常会问到比如RocketMQ的事务是如何实现的呢?学习框架,我们不仅要熟练使用,更要掌握设计及原理,才算熟悉一个框架. 1 RocketMQ 事务使用案例 public class Creat ...

  9. golang mysql连接池原理_[Go] golang实现mysql连接池

    golang中连接mysql数据库,需要使用一个第三方类库github.com/go-sql-driver/mysql,在这个类库中就实现了mysql的连接池,并且只需要设置两个参数就可以实现 一般连 ...

  10. 天线巴伦制作和原理_一文看懂巴伦(功能原理、性能参数、基本类型)

    原标题:一文看懂巴伦(功能原理.性能参数.基本类型) 巴伦(英语为balun)为一种三端口器件,或者说是一种通过将匹配输入转换为差分输出而实现平衡传输线电路与不平衡传输线电路之间的连接的宽带射频传输线 ...

最新文章

  1. jQuery插件—获取URL参数
  2. 策划必须知道的经典理论
  3. iptables 开放远程_JavaWeb项目的部署以及远程调试
  4. ppp在linux下的编译和安装
  5. javascript实例自学手册光盘源码_零基础,自学编程,如何选择语言?
  6. Workstation-CentOS-XShell-YUM源 JAVA大数据Week5-DAY1-linux
  7. rpc:call/4函数解析
  8. 有限域的加减乘除运算
  9. 免费英文文献下载攻略
  10. 《区块链技术与应用》公开课系列笔记——目录导航页
  11. 为什么孩子上学越来越难了?
  12. 错过校招_我们在用户测试中容易错过的事情
  13. 文本对抗:《Semantically Equivalent Adversarial Rules for Debugging NLP Models》
  14. Android仿微信朋友圈图片上传选择器布局
  15. matlab 中阿拉伯字母,常用阿拉伯字母念法
  16. 经典工作自我鉴定范文/实习自我鉴定表
  17. 通达信接口公式怎样进行破解?
  18. 高斯移动热源,熔池流场分布,comsol模拟案例
  19. Nginx 反向代理的知识再温习一下
  20. 第五章. 可视化数据分析图表—图表的常用设置1

热门文章

  1. python123词频统计之哈姆雷特_基于Yarn的Spark环境,统计哈姆雷特词频(1)-阿里云开发者社区...
  2. python如何将抓取的数据保存到excel_Python实现提取XML内容并保存到Excel中的方法...
  3. C#:访问web.config中的常量
  4. 线下广告投放方案_本地餐饮该怎样做好广告投放?传统广告投放的弊端和痛点...
  5. Ubuntu18.04 orb-slam3编译出现的错误 undefined reference to symbol ‘_ZN3MPI8Datatype4FreeEv‘ libmpi_cxx.so
  6. 论文笔记_S2D.31_2015-CVPR_对单张图像进行统一的深度和语义预测
  7. SINet: 使用空间压缩模块和信息遮挡编码器的极轻量人像分割模型
  8. 线性代数【八】二次型
  9. 人工智能+眼科疾病辅助诊断(相关信息搜集)
  10. [Spring MVC] 取控制器返回的ModelAndView/Map/Model/Request的对象