看完这一篇,别在说你学过MySQL了(五)

269 阅读9分钟

大家好,我是Leo。目前在常州从事Java后端开发的工作。这篇是MySQL学习整理系列总结篇。这个系列会与字节,网易,阿里,腾讯,美团,快手的相关朋友一起整理输出。希望帮助更多的朋友早日入大厂!

看完这一篇,别在说你学过MySQL了(一)

看完这一篇,别在说你学过MySQL了(二)

看完这一篇,别在说你学过MySQL了(三)

看完这一篇,别在说你学过MySQL了(四)

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

10. 幻读

10.1 是什么,为什么会有

这种从事务开启到事务结束,如果同一个数据看到不同的结果。我们就称为 幻读

下面我们举一个例子

事务A 按照一定条件进行数据读取, 期间事务B 插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B 新插入的数据 称为幻读

10.2 还能想到哪些

脏读

脏读是在未提交读隔离级别下容易遇到的问题。事务中的修改即使没有提交对其他事务都是可见的,也可以称为脏读

10.3 解决方案

如果是新插入的数据可以采用间隙锁的方式解决幻读的问题。

如果是修改一个数据的话可以采用加锁的方式解决幻读的问题。

隔离级别为,串行化的情况下,幻读是不存在的。因为串行化锁的是整个表。

具体的实现,原理,方式会在11模块介绍MySQL的锁

11. 锁(未做)

11.1 全局锁

命令

11.4 间隙锁

11.5 读写锁

11.6 共享锁

11.7 排他锁

11.8 意向锁

11.9 元数据锁

11.2 表级锁

11.3 行级锁

12. 最左匹配原则

众所周知,MySQL是满足最左匹配原则的。也是面试高频的一个点,一般会让你介绍一下什么是最左匹配原则以及最左匹配原则的应用技巧。下面我们来介绍一下。

假设组合索引为A,B,C。我们分情况一一介绍

  • A,A一起使用完全满足最左匹配原则
  • A,B一起使用完全满足最左匹配原则
  • B,A一起使用完全满足最左匹配原则
  • A,B,C一起使用完全满足最左匹配原则
  • A,C一起使用 部分 满足最左匹配原则
  • B,C一起使用 满足最左匹配原则

根据上述情况我们总结一下,最左原则。即:SQL语句中的对应条件的先后顺序无关。只要出现最左侧的索引树就为最左匹配原则。在explain执行计划中,可以通过key这一列查看是否命中,是否符合最左匹配原则。

个人建议:这里说一下题外话,建议每写一个SQL我们要保存有走执行计划的习惯,如果没命中索引,就把SQL优化一下,时间一长,慢慢的就对SQL优化有了简单的认识,再配上一些理论,你的个人实力绝对会上一层楼的!

13. 如何保证MySQL主从同步

MySQL的主从同步问题,这里我们可以跟面试官介绍一下,binlog的三种格式问题,就是因为这三种格式的存在才保证了MySQL的主从同步问题。

命令参数

binlog_format=‘row’

statement

首先就是第一种statement。记录的是大概的信息,几乎是我们的执行信息,我们看不到具体的逻辑是什么。所以如果同步到从库上,很容易会发现数据不一致的情况。

这里格式的优点就是,记录日志比较简洁,占用空间较小,但是风险较大,一旦数据丢失无法找到相应的数据。

row

第二种就是row格式的binlog日志。这种格式的优点就是,日志丰富,只要有row格式的binlog日志,想干什么操作都可以,丢的数据也可以随时(一般是15天)找回来。唯一的缺点就是日志过于丰富,内存占用过大,如果是在线上的话,磁盘写完之后,风险也是比较大的。需要做一些特殊处理。

比如日志定期备份转移,设置一个失效时间。保存15天内的数据,15天外的一概不管!

mixed

这里格式的出现,是上述的结合体,为什么这么说呢?mixed格式,使用了statement格式的优点,同时也使用了row格式的优点。

我想很多读者会感到比较疑惑,世上岂会有十全十美的事呢?下面我们详细介绍一下。

mixed会多做一个判断,他会判断,这个binlog会不会引起数据不一致这个问题。如果会引起,那么就采用row格式的。如果不会引起,那么就采用statement格式的日志。

主从同步

主库,从库在做数据一致性同步的时候主要依靠的就是binlog日志,如果在我们做操作时,日志保存的比较详细,那么就足矣可以保证主从一致性问题。

这里我们扩展两个问题

①:主从切换时的数据安全性问题。有一个A库和B库,客户端一开始访问的是A库,这个时候做了主从切换,主库从A切换到了B。(数据同步线程具有超级管理员权限)客户端访问B库的这一过程中,如果把从库设置成readonly模式

  • 可以防止其他运营的类的查询语句的误操作。造成数据不一致的问题。
  • 可以防止A和B在切换的时候也会有一些逻辑性的BUG问题

②:主从同步的循环复制问题。节点 A 上更新了一条语句,然后再把生成的 binlog 发给节点 B,节点 B 执行完这条更新语句后也会生成 binlog。(我建议你把参数 log_slave_updates 设置为 on,表示备库执行 relay log 后生成 binlog)。那么,如果节点 A 同时是节点 B 的备库,相当于又把节点 B 新生成的 binlog 拿过来执行了一次,然后节点 A 和 B 间,会不断地循环执行这个更新语句,也就是循环复制了。解决方案如下:

  • 规定两个库的 server id 必须不同,如果相同,则它们之间不能设定为主备关系;
  • 一个备库接到 binlog 并在重放的过程中,生成与原 binlog 的 server id 相同的新的 binlog;
  • 每个库在收到从自己的主库发过来的日志后,先判断 server id,如果跟自己的相同,表示这个日志是自己生成的,就直接丢弃这个日志。

这里不做详细介绍了,为面试打造!详细的技术点看其他文章。

14. MySQL高可用主要体现在哪些

讲到高可用的话,肯定少不了两个策略。可靠性优先策略,可用性优先策略。

面试官问的话肯定要先从源头说起。比如为什么会有高可用,你可以聊一下从硬件的问题,大事务的问题,大表DDL的问题,从库复制能力的问题。这些一系列的问题导致延时,为了高可用的考虑才引进了两个策略。下面介绍了这两个策略是什么。

可靠性优先策略

  • 判断从库B的seconds_behind_master 是否小于某个值,如果大于某个值的话延迟太大会影响业务数据的,所以一定要小于某个值的时候才可以继续下一步
  • 把主库A改成只读状态,readonly改为true
  • 再判断seconds_behind_master的值,直到这个值变成0为止。(因为只有延时足够低,数据才足够安全)
  • 把从库B改成读写状态,也就是把readonly改为flase
  • 最后把业务的请求都打到B上

这里的第二步把主库A改成了只读模式,这是不可用的时间,这段时间都是不可写的,有数据的话只能等待。

可用性优先策略

与可靠性优先策略对比,唯一的区别就是。这里不等同步完成之后再切换过去和状态修改。而是直接把一系列步骤一次性到位。这样是比较危险的,主备切换的可用性优先策略会导致数据不一致。因此,大多数情况下,我都建议你使用可靠性优先策略。毕竟对数据服务来说的话,数据的可靠性一般还是要优于可用性的。

具体的策略根据业务来定! 听的不是很明白的 群里讨论

15. 分布式事务主键ID

前段时间公司上了一套热门方案,分库分表,读写分离,一主多从这类技术栈。考虑到了全局性的唯一ID的问题。我们采用的是雪花算法进行生成唯一ID。

img

  • 第一个部分,是 1 个 bit:0,这个是无意义的。
  • 第二个部分是 41 个 bit:表示的是时间戳。
  • 第三个部分是 5 个 bit:表示的是机房 id,10001。
  • 第四个部分是 5 个 bit:表示的是机器 id,1 1001。
  • 第五个部分是 12 个 bit:表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 id 的序号,0000 00000000。

这个算法可以保证,一个机房的一台机器上,在同一毫秒内,生成了一个唯一的 id。可能一个毫秒内会生成多个 id,但是有最后 12 个 bit 的序号来区分开来。

15.1 优点

(1)高性能高可用:生成时不依赖于数据库,完全在内存中生成。

(2)容量大:每秒中能生成数百万的自增ID。

(3)ID自增:存入数据库中,索引效率高。

15.2 缺点

依赖与系统时间的一致性,如果系统时间被回调,或者改变,可能会造成id冲突或者重复。

15.3 体量考虑

真实开发过程中,除了一线互联网大厂会有那么多的机器,估计我们不会接触那么多的机器,我们可以改进算法,生成18个bit的ID就够我们使用的了。

这里生成多少位的,取决于公司的体量吧