面试官:什么是大事务?小林哥:就是 很大…的…事务??

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

面试官:什么是大事务?小林哥:就是 很大...的...事务??

精彩推荐

一百期Java面试题汇总
SpringBoot内容聚合
IntelliJ IDEA内容聚合
Mybatis内容聚合

最近疫情期间跳槽不易,在外包公司工作了5年的小林在某直聘软件上边投递了好几家互联网公司的java工程师岗位。在经历了快半年的无人问津之后,终于被一家公司的技术leader叫去了面试。

到了南山科技园的某栋大楼地下,看了下时间,距离面试约定时间还有大概15分钟。小王慢慢悠悠地步入了这栋科技大楼,在前台坐下后,过了不久,面试官便赶来了。

面试官

你好,请自我介绍一下吧。

小林

你好,我是xxxxx

面试官扫了下我的简历,发现了简历上的一点:熟悉mysql数据库。这时候面试官笑了笑,仿佛心里头在盘算着后边该怎么问我这块的知识点,我背地一凉。

面试官

聊聊你之前做的项目吧,看这上边的经历,似乎你写的很多项目都是有用到过mysql数据库啊。

小林

嗯嗯,是的,我之前很多的工作经验都是有用到过mysql数据库。(心里暗想:估计接下来要问数据库的知识点了。)

面试官

那你平时对mysql应该有一定的研究吧,我先简单问你几个问题吧。

小林

嗯嗯,可以的。

面试官

我看你简历上边写了商城的项目,为什么要用mysql数据库来存储数据呢?

小林一开始有点蒙。(怎么会问这么奇葩的问题?商品信息存在mysql不是很正常的操作吗?)

小林

商品信息和订单,用户等数据都有一定的关联性,使用关系型数据库进行数据存储会比较合适。而且公司早起业务发展的时候就是使用了mysql数据库,加上市面上mysql数据库在性能,文档等方面也比较成熟,哦对了,mysql对外还是开源免费的,综合这些因素来分析,我觉得使用mysql数据库是一个比较不错的选择。

面试官

嗯嗯,那你在使用mysql存储数据的时候有遇到过哪些问题呢?

小林

嗯嗯,有的。比如说一些sql查询的时间特别久。在工作中我也有对其做过一些优化,也有了解过索引的相关知识点。

(嘿嘿,准备问索引知识了吧,我这块可是准备了很充足的。)

面试官

嗯嗯,那我相信你应该对索引这块了解比较深入,并且有一定经验了吧。那你能讲下你在使用索引的时候遇到过哪些问题吗?

小林

嗯嗯,我有用到过覆盖索引来做一些sql的优化,包括使用一些最左索引前缀的方式进行优化。

面试官

覆盖索引为何能优化sql查询效率呢?能讲解下吗?

小林

因为当覆盖索引生效的时候能够避免“回表查询”操作,减少了io查询的次数。当使用了覆盖索引当时候,查询当数据在叶子节点便可以读取到需要当数值,不需要继续做“回表查询”了。

面试官

哦,那是不是如果覆盖索引没有生效就一定会触发回表查询操作呢?

小林

额。。。不太清楚 (一下子蒙了)

(后来查询了下资料,回表是因为查询当数据在主键索引里面才有数据。但是如果数据库引擎使用了myisam则不需要回表,直接根据对应的叶子地址去查询数据即可)

面试官

咳咳,没事我们继续。你有了解过索引的重建过程吗?

小林

额。。不太清楚 (渐渐又开始蒙了)

面试官

例如我们在工作中发现某张表的数据量和其存储的实际数据数目不匹配,这种情况通常是因为删除了过多的数据,导致表里面的数据空洞过多占用导致的,一般会通过命令去压缩表的体积进行优化。

ps :面试结束后,小林查询了一些资料,发现有一条sql:alter table t engine=InnoDB 可以用于重建整张表的索引数据,将表里以前的一些索引空洞给一并压缩进行重新整合。

假设一棵b+树(innodb)的起初结构如下图所示:

面试官:什么是大事务?小林哥:就是 很大...的...事务??
图片

当我们delete from table_a where id=400 的时候,其实id为400的那个位置并不会被删除,而是会有个标签记录,当前位置可以复用。也就是说会变成下图这种模式:

面试官:什么是大事务?小林哥:就是 很大...的...事务??
图片

此时400的那个位置会空余出来,但是如果我们新插入的数据,其id并不是400,而是600的时候,就不会复用这个位置了。

面试官:什么是大事务?小林哥:就是 很大...的...事务??
图片

因此有的时候,可能我们表里的数据即使删除了一半,体积也反而没有变化。如果不懂得如何去压缩这颗树的话,可能你的磁盘空间就会约占越大,增加企业在服务器存储方面的开销费用。

当然优化技巧也是有的,可以通过执行 alter table t engine=InnoDB 这样的一条sql来重新构建整棵树从而实现索引的压缩效果。

面试官

好吧,那索引的问题先问这么多。你应该对innodb也比较了解吧。

小林

嗯嗯,是的。(应该要问innodb和myisam的区别了)

面试官

你了解innodb的背后架构吗?能说下它内部的线程包含了哪些吗?

小林

额?(这出门前背过,但是不太记得了)

面试官

(引导一下求职者)

innodb背后的线程分为了好几个类型,不同类型的线程负责相关的职责工作。

小林

我记得有好几个线程,但是他们的名字记不太清楚了。

ps:后来小林翻查了以前自己整理的笔记,回顾了关于innodb的线程知识点。大致整理了一下,如下图:

面试官:什么是大事务?小林哥:就是 很大...的...事务??
图片

面试官

好吧,那你对事务了解吗。能讲下什么是大事务吗?

小林

就是 很大...的...事务??

ps:其实大事务是指运行时间比较长,操作的数据比较多的事务。

这类型的事务容易给数据库带来负担:

锁定了过多的数据,造成不必要的拥塞堵塞。

在事务执行的过程中需要堵塞容易引起主从数据同步不一致的情况发生。

当我们执行事务的操作过大,例如说delete某张表里买呢一亿条数据的时候,如果加入了事务保护,那么假设期间出现了异常,整段事务的回滚将会非常消耗机器的性能和耗时。通常可以让研发将大事务分解为多个小事务进行优化处理。

在mysql的二进制日志里面,当多个会话同时访问server执行事务性sql语句的请求时候,binlog会给每个会话单独开启一个线程进行事务性sql的缓存处理。直至当相应的sql执行完毕之后再写入到binlog日志中。

这样做的好处在于能够将不同的事物进行分隔出来处理。并且保证每个写入binlog的事务sql都是完整且正常执行的一个单位。而且如果事务在执行的过程中发生了回滚的话,可以直接在内存中间数据删除,不需要再在日志里面进行记录删除操作。

面试官

额,好吧。那我们mysql相关的知识点先问到这里吧。你可以回去等通知了。

小林

我还有机会吗?......

小林很清楚,自己在以前的工作中过多是偏于crud写业务方面的内容,对于常用技术的底层原理平时也没有做过多的整理和总结,也难怪这次面试会失败。

滴滴滴.... 突然一个陌生的电话响了起来,小林拿起了电话....下一家当面试要开始准备了。

END


面试官:什么是大事务?小林哥:就是 很大...的...事务??

我知道你 “在看面试官:什么是大事务?小林哥:就是 很大...的...事务??

原文始发于微信公众号(Java知音):面试官:什么是大事务?小林哥:就是 很大...的...事务??