本文收录在我开源的《Java学习面试指南》中,目前已经更新有近200道面试官常考的面试题,涵盖了Java系列、Redis系列、MySQL系列、多线程系列、Kafka系列、JVM系列、ZooKeeper系列等等。GitHub地址:https://github.com/hdgaadd/JavaGetOffer,相信你看了一定会有所收获。
1. MySQL主从复制
面试官:MySQL主从复制了解吧?
回答这个问题前,大家先思考下MySQL主从复制起到了什么作用。知道技术诞生的缘由,技术原理和步骤的整个逻辑推导就很清晰。
MySQL主从复制把数据库数据同步到多台服务器上,同理就可以把读操作分布到多台服务器上,这对于那些读密集型的系统性能提升是很大的。
数据有了多台服务器的备份,就不怕单点故障。我们只需要快速切换到另一台MySQL服务器即可,减少了数据库宕机的时间。
MySQL主从复制主要是利用了主库的Binary Log二进制文件来进行数据复制。
复制的步骤可以分为三步。
- 主库根据数据库事务提交的顺序,把数据更改记录到二进制文件Binary Log中。
- 备库建立TCP/IP连接后通过IO线程获取Binary Log,同时将Binary Log复制到中继日志Relay Log。
- 备库再读取中继日志Realy Log中的事件,重放到备库的数据里。
如果你现在有两台MySQL,一台版本是03年的MySQL5.0,另一台是18年的MySQL8.0.11。新版本可以作为老版本的从服务器,但反过来是不可行的。MySQL的复制具有向后兼容性,老版本可能无法解析新版本的新特性,甚至复制的文件格式都差异太大。
1.1 二进制文件的日志格式
面试官:那Binary Log日志格式知道有哪些?
MySQL提供了三种二进制日志格式用于主从复制。
- 基于语句的二进制文件,保存了在MySQL主库所有执行过的数据变更语句,相当于从库需要把主库执行过的SQL都执行一遍。
- 基于行的二进制文件,会把每条被改变的行记录都作为事件写入到二进制文件中。缺点也很明显,行记录的事件是很多的,可能会导致二进制文件大小过大。这种复制模式通常来说让带宽压力更大些。
- 混合模式。MySQL能够在以上两种复制模式之间动态切换,默认会使用基于语句的复制方式,如果发现无法被正确复制,就切换成基于行的复制方式。
1.2 二进制文件选择
面试官:知道哪种二进制格式比较好吗?
基于语句的二进制文件,有可能会出现数据不一致的问题。例如某条删除语句SQL要删除10000条数据中的1000条,这条删除语句没有采用order by进行排序。如果主、从服务器存储数据的顺序不一样,就会导致每次执行删除的数据都是不同的。
# 没有排序的删除语句
delete from test where name = 'JavaGetOffer' limit 1000;
# 有排序的删除语句
delete from test where name = 'JavaGetOffer' order by id asc limit 1000;
混合模式的话不确定因素太多,两种复制模式的不断切换可能回导致二进制日志出现不可预测的事件。如果从服务器复制该二进制文件后的数据库状态是混乱无序的,那整个复制的过程就没有意义了。
一般来说选择行的复制会更加稳妥,也更加安全。虽然二进制文件过大会带来带宽压力大和复制较慢的问题,但比起数据安全性来说,显然后者更加重要。
1.3 主从模式的优点
面试官:那MySQL主从模式有什么好处?
大家如果有细看第一个面试官问题
就知道上文已经有答案了,我这里再总结下。
- 对于读密集的应用程序,可以利用MySQL主从模式将读操作负载均衡到多个从服务器上,提高系统的抗压能力。
- MySQL主从还可以避免单点问题,有效减少数据库宕机的时间。同时多个数据源支持查询保证了数据库的可用性。
- 另外如果需要对MySQL进行版本升级,可以先对备库进步版本升级,保证查询可用的同时,再慢慢升级其他全部MySQL实例。
2. 全局事务标识符
面试官:如果把二进制文件丢给从库,从库是不是复制整个文件?
能设计出MySQL的聪明人肯定不会这么傻。如果二进制文件包含了已存在的数据,就会造成数据重复了。
MySQL从库只会复制它本身缺失的最新数据,利用二进制文件里的全局事务标识符(GTID)就可以找到对应的二进制文件具体位置。
主库的每一次事务提交都会被分配一个唯一的全局事务标识符,这个标识由server_uuid和一个递增的事务编号组成。
MySQL从库是根据本身当前全局事务标识符找到二进制文件对应位置才进行复制而不是复制全部。
创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️