Java架构技术进阶

被面试官问“Mysql”,update 语句到底做了些什么?

2020-02-19  本文已影响0人  代码小当家

推荐阅读:

47天时间,洒热血复习,我成功“挤进”了字节跳动(附Java面试题+学习笔记+算法刷题)​zhuanlan.zhihu.com

图标 面试“阿里云”居然一面就惨被吊打?幸终得内推机会,4面喜提华为offer​zhuanlan.zhihu.com 图标

问题:

一条简单的update 的语句到底牵扯了多少的东西?你能完全说明白吗?

来看看具体流程:

## student 只有id, 和name  两个字段,且只有id 一个主键,无其他索引。update student set name = 'gxw' where id = 2复制代码
  1. 开启事务,将原内容写入undo log。
  2. 去Buffer Pool 中 查找id =2 所对应的数据。
  3. 如果在Buffer Pool中查找到了对应的数据,那么直接在Buffer Pool 中直接修改对应数据。如果没有找到,那么先从磁盘中找到对应数据,然后加载到Buffer Pool 中进行修改。
  4. 将更新的内容写入redo log。
  5. 如果开启了binlog ,还会写入binlog日志。
  6. 事务提交进入prepare 阶段,将redo log 刷入磁盘
  7. 事务提交进入commit 阶段, 将binlog 输入磁盘

分析下每个阶段干了什么,为什么要这么做?

步骤1,mysql 默认配置每个单独的更新语句都会开启一个事务。所以上面这个语句第一步肯定是开启一个事务。开启事务的同时,把原纪录写入undo log。

为什么需要写undo log?

步骤2和步骤3,在Buffer Pool 中查找数据并修改。 Buffer Pool 在这就不多解释了,我已经有专门的文章介绍,有兴趣的同学可以翻看我的其他文章。一句话概括就是问题避免过多的磁盘操作,增加的缓存。

步骤4, 将新内容写入redo log。

为什么需要redo log?

步骤5,写binlog 。 相信很多人对binlog 比较熟悉,它可以开启,也可以关闭。它不影响事务的功能,但它提供了额外的功能,比如回溯的能力,比如你希望把数据库放回到2020-01-01 00:00:00 的时候,这时候就需要借助binlog了。 当然binlog 还有一个功能是实现主备同步。 Mysql 的 一主多从,双主多从等都是通过binlog 实现的。

步骤6,步骤7, 事务两阶段提交。(限制于篇幅详细不展开了,以后开专门的文章介绍)。 简单的说它是保证redo log 和 binlog 的一致性。当我们输入COMMIT 命令时,其实是经过了prepare 和commit 两个阶段的。

到这就介绍完一个最简单的更新语句的流程了。如果再复杂点的情况呢?

当存在二级非唯一索引的时候

什么意思呢? 比如产品提了个需求说,我需要按照姓名来查找数据。为了提高搜索速度,我们可能就会为name 字段加上索引,由于姓名允许重复,那这个索引就不会被设置成唯一索引。假设索引名为index_name我们知道index_name 的数据也会被存放在各个数据页中。那么上面的修改语句,将id = 2 的name 修改为'gxw' 。那么除了修改数据页中的数据,index_name 的索引页中的数据也需要相应修改。如果是你,你会怎么做? 从Buffer Pool 中的查找对应的index_name 中的数据,如果存在则修改,如果不存在,则到磁盘中查找数据加载到Buffer Pool中进行修改。可以看到这里需要一次磁盘操作,如果有多个二级非唯一索引那可能需要多次磁盘操作,影响效率。Mysql 的工程师为了优化,就又加入了change log。也就是说如果一个表中有二级非唯一索引,那么执行update 操作可能会用到change log

总结:

一个简单的更新语句,会涉及到的东西: undo log , Buffer Pool, redo log ,change log , binlog 。现在你可以不了解他们具体是如何工作的,但希望通过这篇文章你已经知道了他们到底是为了什么目的而存在的。

作者:小歪同学
链接:https://juejin.im/post/5e47d7f46fb9a07cd942a506

上一篇下一篇

猜你喜欢

热点阅读