MySQL八股文连环45问,你能坚持第几问?

Posted IT邦德

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL八股文连环45问,你能坚持第几问?相关的知识,希望对你有一定的参考价值。

📢📢📢📣📣📣
哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10年DBA工作经验
一位上进心十足的【大数据领域博主】!😜😜😜
中国DBA联盟(ACDU)成员,目前从事DBA及程序编程
擅长主流数据Oracle、mysql、PG 运维开发,备份恢复,安装迁移,性能优化、故障应急处理等。
✨ 如果有对【数据库】感兴趣的【小可爱】,欢迎关注【IT邦德】💞💞💞
❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️

文章目录

前言

文人从事多年面试工作,将MySQL面试分享给大家,希望大家顺利拿下offer

🐴 第一股 基础篇

🚀 1.1.请简述MySQL数据库的优点?

Mysql 是开源的,所以你不需要支付额外的费用。
Mysql 支持大型的数据库,可以处理拥有上千万条记录的大型数据库。
MySQL 使用标准的 SQL 数据语言形式。
Mysql 可以允许于多个系统上,并且支持多种语言。
Mysql 对 php 有很好的支持,PHP 是目前最流行的 Web 开发语言。
MySQL 支持大型数据库,支持 5000 万条记录的数据仓库。
Mysql 是可以定制的,采用了 GPL 协议,你可以修改源码来开发自己的 Mysql 系统。

🚀 1.2.说一说三个范式

第一范式(1NF):
数据库表中的字段都是单一属性的,不可再分。
这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
第二范式(2NF):
在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分
第三范式(3NF):
在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键
总结:
在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。

🚀 1.3.事务的四大特性(ACID)介绍一下?

原子性(atomicity,或称不可分割性): 事务的所有操作要么全部成功,要么全部回滚。

一致性(consistency): 总是从一个一致性的状态转换到另一个一致性的状态
隔离性(isolation): 多个事务并发执行时,一个事务的执行不应影响其他事务的执行

持久性(durability): 已被提交的事务对数据库的修改应该永久保存在数据库中。

🚀 1.4.在 Linux 下安装MySQL有哪几种方式?

RPM (Redhat Package Manage):
安装简单,适合初学者学习使用,一台服务器只能安装一个 MySQL,Red Hat Enterprise Linux / Oracle Linux
二进制( Binary Package):
安装简单;可以安装到任何路径下,灵活性好;一台服务器可以安装多个 MySQL,Linux - Generic
源码( Source Package):
在实际安装的操作系统进行可根据需,要定制编译,最灵活;性能最好;服务器安装多个Source Code

🚀 1.5.为什么升级 MySQL,升级前注意事项?

为什么升级MySQL
1.基于安全考虑
2.基于性能和稳定性考虑:mgr 复制 ,并行复制 writeset 等功能,性能提升
3.新的功能:Hash join ,窗口函数,DDL 即时,json 支持
4.原始环境中版本太多,统一版本
5.8.0 版本基本已到稳定期,可以大量投入生产环境中

升级前注意事项
1.注意字符集设置:
为了避免新旧对象字符集不一致的情况,在配置文件将字符集和校验规则设置为旧版本的字符集和比较规则。
2.密码认证插件变更:
为了避免连接问题,可以仍采用 5.7 的 mysql_native_password 认证插件。*
3.sql_mode 支持问题:
8.0 版本 sql_mode 不支持 NO_AUTO_CREATE_USER,要避免配置的 sql_mode 中带有NO_AUTO_CREATE_USER。*
4.是否需要手动升级系统表:
在 MySQL 8.0.16 行 版本之前,需要手动的执行 mysql_upgrade 在 来完成该步骤的升级,在 MySQL8.0.16 版本及之后是由 mysqld 来完成该步骤的升级。
5.高可用架构:
需要先升级从库,再逐步升级主库

🚀 1.6.存储引擎如何选择?

如果没有特别的需求,使用默认的Innodb即可。
InnoDB 引擎由于其对事务参照完整性,以及更高的并发性等优点开始逐步的取代 MyISAM
MyISAM:
以读写插入为主的应用程序,比如博客系统、新闻门户网站。
Innodb:
更新(删除)操作频率也高,或者要保证数据的完整性,并发量高,支持事务和外键。比如OA自动化办公系统,如下是InnoDB引擎的4大特点
1.插入缓冲(insert buffer)
2.二次写(double write)
3.自适应哈希索引(ahi)
4.预读(read ahead)

🚀 1.7.存储引擎如何选择?

为了达到事务的四大特性,数据库定义了4种不同的事务隔离级别,
由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,
这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
1.READ-UNCOMMITTED(读取未提交):
最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
2.READ-COMMITTED(读取已提交):
允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
3.REPEATABLE-READ(可重复读):
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
4.SERIALIZABLE(可串行化):
最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

这里需要注意的是:
Mysql 默认采用的 REPEATABLE_READ隔离级别
Oracle 默认采用的 READ_COMMITTED隔离级别

🐴 第二股 SQL篇

🚀 2.1 简述下SQL及分类?

结构化查询语言(Structured Query Language)简称SQL,是一种数据库查询语言。
作用:用于存取数据、查询、更新和管理关系数据库系统。
基本的分类如下:
1.数据查询语言(Data Query Language, DQL)
负责进行数据查询而不会对数据本身进行修改的语句,这是最基本的SQL语句。
2.数据定义语言 (Data Definition Language, DDL)
负责数据结构定义与数据库对象定义的语言,由CREATE、ALTER与DROP三个语法所组成
3.数据操纵语言(Data Manipulation Language, DML)
负责对数据库对象运行数据访问工作的指令集,以INSERT、UPDATE、DELETE三种指令为核心,
分别代表插入、更新与删除。
4.数据控制语言 (Data Control Language)
它可以控制特定用户账户对数据表、查看表、预存程序、用户自定义函数等数据库对象的控制权。
由 GRANT 和 REVOKE 两个指令组成。

🚀 2.2 drop、delete与truncate的区别是什么?

三者都表示删除,但是三者有一些差别:
在不再需要一张表的时候,用drop;
在想删除部分数据行时候,用delete;
在保留表而删除所有数据的时候用truncate。

🚀 2.3 MySQL六种关联查询是什么?

1.交叉连接(CROSS JOIN)
2.内连接(INNER JOIN)
3.外连接(LEFT JOIN/RIGHT JOIN)
4. 联合查询(UNION与UNION ALL)
5.全连接(FULL JOIN)
6.交叉连接(CROSS JOIN)

🚀 2.4 MySQL中 in 和 exists 区别?

mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。
1.如果查询的两个表大小相当,那么用in和exists差别不大。
2.如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in。
not in 和not exists:如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not extsts的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

🚀 2.5 基于MySQL简述下SQL的生命周期

1.应用服务器与数据库服务器建立一个连接
2.数据库进程拿到请求sql
3.解析并生成执行计划,执行
4.读取数据到内存并进行逻辑处理
5.通过步骤一的连接,发送结果到客户端
6.关掉连接,释放资源

🐴 第三股 运维篇

🚀 3.1 MySQL有哪些数据类型?

MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型
1.数值类型
整数类型:TINYINT、SMALLINT、MEDIUMINT、INT 或 INTEGER、BIGINT
带小数的类型:FLOAT(单精度)、DOUBLE(双精度)、DECIMAL(定点数)
2 日期和时间类型
DATE:YYYY-MM-DD 日期值
TIME:HH:MM:SS 时间值或持续时间
YEAR:YYYY 年份值
DATETIME:YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP:YYYYMMDDHHMMSS 混合日期和时间值,时间戳
3.字符串类型
CHAR:定长字符串 0-255 字节
VARCHAR:0-65535 字节 变长字符串 --频繁改变的列建议用vachar 类型
BLOB:0-65535 字节 二进制形式的长文本数据,二进制大对象
TEXT:0-65535 字节 长文本数据 、varchar 的加长增强版
LONGTEXT:0-4294967295 字节极大文本数据
ENUM: 1-2 字节 枚举类型(单一值)
SET:1-8 字节 一个集合

🚀 3.2 MySQL的约束有哪几种?

NOT NULL:
用于控制字段的内容一定不能为空(NULL)。
UNIQUE:
控件字段内容不能重复,一个表允许有多个 Unique 约束。
PRIMARY KEY:
也是用于控件字段内容不能重复,但它在一个表只允许出现一个。
FOREIGN KEY:
用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
CHECK:
用于控制字段的值范围。

🚀 3.3 索引设计的原则?

1.适合索引的列是出现在where子句中的列,或者连接子句中指定的列
2.基数较小的类,索引效果较差,没有必要在此列建立索引
3.使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间
4.不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。

🚀 3.4 请简述下存储过程及其优点?

存储过程是一组为了完成特定功能的SQL语句集,经过编译之后存储在数据库当中,
用户只需要调用存储过程即可(给特定的参数)

存储过程的优点
a.增强了SQL语句的灵活性
b.固定的业务模块化封装,较少开发重复性
c.执行速度很快
d.存储过程被做为一种安全机制,充分的得到了利用
举例说明如下:
需求:输出当前数据库的用户
CREATE PROCEDURE pro_count_mysql(OUT P_o_cnt int)
BEGIN
select count(*) into P_o_cnt from mysql.user;
END;
#调用
mysql> call pro_count_mysql(@s);
mysql> select @s;

🚀 3.5 MySQL如实使用定时任务(event)?

事件(event)是MySQL在相应的时刻调用的过程式数据库对象。
一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理的,也就是所谓的“事件调度器”。
事件和触发器类似,都是在某些事情发生的时候启动。
事件是根据调度事件来启动的,事件取代了原先只能由操作系统的计划任务来执行的工作,
而且MySQL的事件调度器可以精确到每秒钟执行一个任务,
而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精确到每分钟执行一次。

🚩🚩 定时任务的使用

SHOW VARIABLES LIKE ‘%event_sche%’;
开起定时任务
SET GLOBAL event_scheduler = 1;
关闭定时任务
SET GLOBAL event_scheduler = 0;
如果需要长期开起定时任务需要在my.ini中配置 event_scheduler = on
这里设置的就是从2022-08-04-03 00:10:00 开始每1天执行一次。
创建定时任务的SQL语句如下。
CREATE EVENT Untitled
ON SCHEDULE
EVERY ‘1’ DAY STARTS ‘2022-08-04-03 00:10:00’ + INTERVAL ‘2’ SECOND
DO select * from mysql.user;

🐴 第四股 体系架构

🚀 4.1 请简述下MySQL的体系架构

MySQL 由数据库和数据库实例组成,是单进程多线程架构
1.数据库:
物理操作系统文件或者其它文件的集合,在 mysql中,数据库文件可以是 frm、myd、myi、ibd 等结尾的文件,当使用 bdb 存储引擎时候,不是 os 文件,是存放于内存中的文件。
2.数据库实例:
由数据库后台进程/线程以及一个共享内存区组成,共享内存可以被运行的后台进程/线程所共享。

🚀 4.2 MySQL的参数文件位置及如何配置?

Linux的位置:
Linux默认的参数文件为/etc/my.cnf,但是也不排除其他位置,在 mysqld 启动的时候,可以加上–defaults-file 参数,该参数指定了参数文件的名称。
[root@jeames ~]# mysql --help | grep ‘my.cnf’
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf
Windows的位置:

参数文件内容
Windows系统配置:
[mysqld]
port=3306
basedir=E:\\mysql-8.0.26-winx64
datadir=E:\\mysql-8.0.26-winx64\\data80263307
max_connections=200
max_connect_errors=10
character-set-server=utf8mb4
default-storage-engine=INNODB
default_authentication_plugin=mysql_native_password
Linux系统配置:
[mysqld]
mysqld=/usr/local/mysql80/mysql8019/bin/mysqld_safe
mysqladmin=/usr/local/mysql80/mysql8019/bin/mysqladmin
port=3509
basedir=/usr/local/mysql80/mysql8019
datadir=/usr/local/mysql80/mysql8019/data
socket=/usr/local/mysql80/mysql8019/data/mysqls80193509.sock
default_authentication_plugin=mysql_native_password
server_id=80193509
log-bin
default-time-zone = ‘+8:00’
log_timestamps = SYSTEM
skip-name-resolve
character_set_server=utf8mb4

🚀 4.3 MySQL参数持久化是什么?

MySQL 的动态参数可以在运行时通过 SET GLOBAL 命令来更改,
但是这种更改只会临时生效,到下次启动时数据库又会从配置文件中读取。
在MySQL8.0之前参数文件的动态修改不能写到配置文件,
为了改善这一问题MySQL8.0支持了动态修改参数并将其保存到一个新的参数文件文件中mysqld-auto.cnf,
默认在$datadir目录下,在所有的参数之后启动,权限为SYSTEM_VARIABLES_ADMIN or SUPER。

mysql> set persist max_connections=300;
数据字典查询
mysql> SELECT * FROM performance_schema.persisted_variables;
持久化清除:
对于已经持久化了变量,可通过 reset persist 命令清除掉,

注意,其只是清空 mysqld-auto.cnf 和 performance_schema.persisted_variables 中的内容
MySQL 会将该命令的配置保存到数据目录下的 mysqld-auto.cnf 文件中,下次启动时会读取该文件,
用其中的配置来覆盖缺省的配置文件。不建议手动修改该文件,因为其内容是 json 格式的,
其有可能导致数据库在启动过程中因解析错误而失败,有些参数不支持持久化的。
非持久化:Nonpersistent
持久化:PERSIST
只读持久化:PERSIST_ONLY

🚀 4.4 socket什么,如何用socket登陆

Linux系统下 本地连接 mysql 可以采用 linux 域套接字 socket 方式 ,需要一个套接字 socket 发文件,
可以由参数 socket控制,一般默认在/tmp 目录下,也可以通过如下方式查看

[root@jeames ~]# ps -ef | grep mysql
mysql> show variables like ‘socket’;
mysql> select @@socket;
如果 socket 录 文件丢失,那么会导致不能从本地登录 mysql ,可以通过重启的方式来重新生成。

mysql.sock是mysql的主机和客户机在同一host上的时候,
使用unix domain socket做为通讯协议的载体,它比tcp快。
对mysql.sock来说,其作用是程序与mysqlserver处于同一台机器,发起本地连接时可用。

[root@jeames ~]# mysql -uroot -p -S /tmp/mysql.sock

🚀 4.5 MySQL表结构文件有哪些?

InnoDB 中用于存储数据的文件总共有两个部分,一是系统表空间文件,
包括 ibdata1、 ibdata2 等文件,其中存储了 InnoDB 系统信息和元数据,是所有表公用的,
另一个是.idb文件,是每张表独有的。
.ibd 文件就是每一个表独有的表空间,文件存储了当前表的数据,索引数据和插入缓冲等信息

innodb 包括 ibd 和 frm,当你启用了 innodb_file_per_table,表被存储在他们自己的表空间里
mysql> show variables like ‘innodb_file_per_table’;


MySQL8.0以后没有.frm了,元数据都存在系统表空间里ibdata1、 ibdata2

🚀 4.6 错误日志如何配置?

错误日志对 mysql的启动、运行、关闭过程进行了记录,
MySQL DBA 在遇到问题时候,第一时间应该查看这个错误日志文件,该文件不但记录了出错信息,
还记录了一些警告信息以及正确信息,这个 error 日志文件类似于 oracle 的 alert 文件。

可以通过“show variables like ‘log_error’;”命令查看错误日志的路径

【配置方法】
默认是启动的,一般以err做后缀名,需要在参数文件中配置
先找到参数文件
log_error = /usr/local/mysql/data/error.err

🚀 4.6 慢查询日志是什么?如何配置

当查询超过一定时间没有返回结果的时候,才会记录进慢查询日志。
• 慢查询日志可以帮助 DBA 找出执行效率缓慢的 SQ语句,为数据库优化工作提供帮助。
• 慢查询日志默认是不开启的,建议开启慢查询日志。
• 当需要进行采样分析时手工开启。
【慢查询日志开启】
关于慢查询日志,主要涉及到下面几个参数:
slow_query_log :是否开启慢查询日志功能(必填)
slow_query_log_file:慢查询日志文件及位置
long_query_time :超过设定值,将被视作慢查询,并记录至慢查询日志文件中(必填)
也就是说,只有满足以上三个条件,“慢查询功能”才可能正确开启。

参数文件修改如下:
修改配置文件my.cnf,在[mysqld]下的下方加入
[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 1
重启MySQL服务service mysqld restart即可

🚀 4.7 Redo与Binlog的区别是?

所有的数据库都是日志先行,先写日志,再写数据文件,所以才会有 redo log 的规则。
为了保证事务的持久性,mysql的InnoDB 采用了 WAL 技术,WAL 的全称是 Write-Ahead Logging

1.Redo Log:

Redo Log 是 InnoDB 存储引擎提供的一种物理日志结构,用来描述对底层数据页操作的具体内容,记录物理页的修改,主要用于实现崩溃恢复(crash-recover),并提升磁盘操作效率。

2.Binlog:

Binlog是 MySQL Server 本身提供的一种逻辑日志,和具体存储引擎无关,描述的是数据库所执行的 SQL 语句或数据变更情况,主要用于数据复制和增量恢复。

🐴 第五股 备份恢复篇

🚀 5.1 MySQL备份方式有哪些?

1、根据是否需要数据库离线
冷备(cold backup):需要关mysql服务,读写请求均不允许状态下进行;
温备(warm backup): 服务在线,但仅支持读请求,不允许写请求;
热备(hot backup):备份的同时,业务不受影响。
2、根据要备份的数据集合的范围
完全备份:full backup,备份全部字符集。
增量备份: incremental backup 上次完全备份或增量备份以来改变了的数据,不能单独使用,要借助完全备份,备份的频率取决于数据的更新频率。
差异备份:differential backup 上次完全备份以来改变了的数据。
建议的恢复策略:
完全+增量+二进制日志
完全+差异+二进制日志

🚀 5.2 简述下PXB的备份?

第三方工具,是1款开源的mysql的备份恢复工具,
Percona为MySQL和MongoDB提供免费的开源软件,可以在线热备
特点:
a.备份速度快
b.备份过程不影响事务
c.可以实现压缩,进行备份的校验

– 备份
mkdir -p /bk/
xtrabackup -uroot -proot -S/tmp/mysql.sock --backup --target-dir=/bk/full

🚀 5.3 对MySQL表级别误操作有哪些工具?

1.binlog2sql
从MySQL binlog解析出你要的SQL。根据不同选项,
你可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。
2.my2sql
go版MySQL binlog解析工具,通过解析MySQL binlog ,可以生成原始SQL、回滚SQL、去除主键的INSERT SQL等,也可以生成DML统计信息。类似工具有binlog2sql、MyFlash、my2fback等,本工具基于my2fback、binlog_rollback工具二次开发而来。
3.MyFlash
MyFlash是由美团点评公司技术工程部开发维护的一个回滚DML操作的工具。该工具通过解析v4版本的binlog,完成回滚操作。相对已有的回滚工具,其增加了更多的过滤选项,让回滚更加容易。
具体恢复参考CSDN博客:https://blog.csdn.net/weixin_41645135/article/details/122643153

🚀 5.4 MySQL常用的备份工具有哪些?

常用备份工具mysql复制
逻辑备份(mysqldump,mydumper)
物理备份(copy,xtrabackup)
备份工具差异对比
1.mysql复制相对于其他的备份来说,得到的备份数据比较实时。
2.逻辑备份:分表比较容易。
mysqldump备份数据时是将所有sql语句整合在同一个文件中;
mydumper备份数据时是将SQL语句按照表拆分成单个的sql文件,
每个sql文件对应一个完整的表。
3.物理备份:拷贝即可用,速度快。
copy:直接拷贝文件到数据目录下,可能引起表损坏或者数据不一致。
xtrabackup对于innodb表是不需要锁表的,对于myisam表仍然需要锁表。

🚀 5.5 MySQL备份计划如何制定?

视库的大小来定,一般来说 100G 内的库,可以考虑使用 mysqldump 来做,
因为 mysqldump更加轻巧灵活,备份时间选在业务低峰期,
可以每天进行都进行全量备份(mysqldump 备份出来的文件比较小,压缩之后更小)。
100G 以上的库,可以考虑用 xtranbackup 来做,备份速度明显要比 mysqldump 要快。
一般是选择一周一个全备,其余每天进行增量备份,备份时间为业务低峰期。

🚀 5.6 备份恢复失败如何处理

首先在恢复之前就应该做足准备工作,避免恢复的时候出错。
比如说备份之后的有效性检查、权限检查、空间检查等。
如果万一报错,再根据报错的提示来进行相应的调整。

🚀 5.7 数据表损坏的修复方式有哪些?

使用 myisamchk 来修复,具体步骤:

1)修复前将mysql服务停止。
2)打开命令行方式,然后进入到mysql的/bin目录。
3)执行myisamchk –recover
数据库所在路径/*.MYI 使用repair table 或者 OPTIMIZE table命令来修复,

REPAIR TABLE table_name 修复表
OPTIMIZE TABLE table_name 优化表
REPAIR TABLE 用于修复被破坏的表。
OPTIMIZE TABLE 用于回收闲置的数据库空间,
当表上的数据行被删除时,所占据的磁盘空间并没有立即被回收,
使用了OPTIMIZE TABLE命令后这些空间将被回收,
并且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)

🐴 第六股 高可用篇

🚀 6.1 主从复制的作用及解决的问题是?

1.主从复制的作用
主数据库出现问题,可以切换到从数据库。
可以进行数据库层面的读写分离。
可以在从数据库上进行日常备份。
2.解决的问题
数据分布:随意开始或停止复制,并在不同地理位置分布数据备份
负载均衡:降低单个服务器的压力
高可用和故障切换:帮助应用程序避免单点失败
升级测试:可以用更高版本的MySQL作为从库

🚀 6.2 读写分离有哪些解决方案?

读写分离是依赖于主从复制,而主从复制又是为读写分离服务的。
方案一
使用mysql-proxy代理 优点:直接实现读写分离和负载均衡,不用修改代码,
master和slave用一样的帐号,mysql官方不建议实际生产中使用 缺点:降低性能, 不支持事务
方案二
使用AbstractRoutingDataSource+aop+annotation在dao层决定数据源。 如果采用了mybatis,
可以将读写分离放在ORM层,比如mybatis可以通过mybatis plugin拦截sql语句,
所有的insert/update/delete都访问master库,所有的select 都访问salve库,这样对于dao层都是透明。
plugin实现时可以通过注解或者分析语句是读写方法来选定主从库。不过这样依然有一个问题,
也就是不支持事务, 所以我们还需要重写一下DataSourceTransactionManager,
将read-only的事务扔进读库, 其余的有读有写的扔进写库。
方案三
使用AbstractRoutingDataSource+aop+annotation在service层决定数据源,
可以支持事务. 缺点:类内部方法通过this.xx()方式相互调用时,aop不会进行拦截,需进行特殊处理。

🚀 6.3 什么是MySQL的GTID?

GTID(Global Transaction ID,全局事务ID)是全局事务标识符,
是一个已提交事务的编号,并且是一个全局唯一的编号。
GTID是从MySQL 5.6版本开始在主从复制方面推出的重量级特性。
GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。
GTID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。
GTID有如下几点作用:
① 根据GTID可以知道事务最初是在哪个实例上提交的。
② GTID的存在方便了Replication的Failover。
因为不用像传统模式复制那样去找master_log_file和master_log_pos。
③ 基于GTID搭建主从复制更加简单,
确保每个事务只会被执行一次。

🚀 6.4 分库分表和表分区的区别?

表分区(Partitioning)可以将一张表的数据分别存储为多个文件。
如果在写 SQL 的时候,遵从了分区规则,
那么就能把原本需要遍历全表的工作转变为只需要遍历表里某一个或某些分区的工作。
这样降低了查询对服务器的压力,提升了查询效率。如果分区表使用得当,
那么也可以大规模地提升 MySQL 的服务能力。
但是这种分区方式,一方面,在使用的时候必须遵从分区规则写 SQL语句,
如果不符合分区规则,那么性能反而会非常低下;另一方面,分区的结果受到 MySQL 实例,
或者说 MySQL 单实例的数据文件无法分布式存储的限制,不管怎么分区,
所有的数据还是都在一个服务器上,没办法通过水平扩展物理服务的方法把压力分摊出去。
分表与分区的区别在于:分区一般都是放在单机里的,
从逻辑上来讲只有一张表,是 MySQL 的一种内部实现;
而分表则是将一张表分解成多张表,分库分表需要代码实现。
分库分表和分区并不冲突,可以结合使用。

🚀 6.5 简述下MySQL数据库常用的中间件

1.Cobar 属于阿里 B2B 事业群,始于 2008 年,在阿里服役 3 年多,
接管 3000+个 MySQL 数据库的 schema,集群日处理在
线 SQL请求 50 亿次以上。由于 Cobar 发起人的离职,Cobar停止维护。
2.Mycat 是开源社区在阿里 Cobar 基础上进行二次开发,
解决了 cobar 存在的问题,并且加入了许多新的功能在其中。青出于蓝而胜于蓝。
3.OneProxy基于 MySQL官方的 proxy思想利用 c进行开发的,
OneProxy是一款商业收费的中间件。舍弃了一些功能,专注在性能和稳定性上。
4.kingshard 由小团队用 go 语言开发,还需要发展,需要不断完善。
5.Vitess 是 Youtube生产在使用,架构很复杂。不支持 MySQL原生协议,使用需要大量改造成本。
6.Atlas 是 360 团队基于 MySQL proxy改写,功能还需完善,高并发下不稳定。
7. MaxScale是 mariadb(MySQL原作者维护的一个版本)研发的中间件。

8. MySQL Route是 MySQL官方 Oracle公司发布的中间件。

🚀 6.5 分库分表标准及类型是?

1.标准:
存储占用 100G+
数据增量每天 200w+
单表条数 1 亿条+
2.类型:
① 分库:垂直分库、水平分库
② 分表:垂直分表、水平分表
分库是指把一个数据库拆分为多个数据库,一般分为垂直分库和水平分库。
分表指的是通过一定规则,将一张表分解成多张不同的表,一般分为垂直分表和水平分表。

🐴 第七股 性能优化篇

🚀 7.1 主键使用自增ID还是UUID?

推荐使用自增ID,不要使用UUID。
因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,
也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),
如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,
由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,
然后导致产生很多的内存碎片,进而造成插入性能的下降。

总之,在数据量大一些的情况下,用自增主键性能会好一些。 关于主键是聚簇索引,
如果没有主键,InnoDB会选择一个唯一键来作为聚簇索引,
如果没有唯一键,会生成一个隐式的主键。

🚀 7.2 如何优化子查询

1.用关联查询替代
2.优化GROUP BY和DISTINCT 这两种查询据可以使用索引来优化,是最有效的优化方法
3.关联查询中,使用标识列分组的效率更高 如果不需要ORDER BY,
进行GROUP BY时加ORDER BY NULL,MySQL不会再进行文件排序。
4.WITH ROLLUP超级聚合,可以挪到应用程序处理

🚀 7.3 对慢查询都怎么优化?

1.首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。

2.分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。

如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。

🚀 7.4 执行计划中Explain常见的扫描方式有哪些?

最为常见的扫描方式有:
system:系统表,少量数据,往往不需要进行磁盘IO;
const:常量连接;
eq_ref:主键索引(primary key)或者非空唯一索引(unique not null)等值扫描;
ref:非主键非唯一索引等值扫描;
range:范围扫描;
index:索引树扫描;
ALL:全表扫描(full table scan);
上面各类扫描方式由快到慢:
system > const > eq_ref > ref > range > index > ALL
执行计划具体参考CSDN博客:
https://jeames.blog.csdn.net/article/details/122772870

🐴 第八股 故障处理篇

🚀 8.1 MySQL root密码忘记了怎么办?

在MySQL中,若密码丢失则无法直接找回,只能通过特殊方式来修改密码。
1.Linux环境
步骤1:先停止MySQL服务
步骤2:启动 MySQL 服务
mysqld_safe --defaults-file=/etc/my.cnf --skip-grant-tables &
2.Windows环境
若 MySQL 是 8.0 且安装在 Windows 上,则需要加上–shared-memory 参数:
G:\\mysql-8.0.23-winx64\\bin\\mysqld --datadir=G:\\mysql-8.0.23-winx64\\data80323308 --console --skip-grant-tables --shared-memory
然后再开一个窗口,执行下面命令
cd G:\\mysql-8.0.23-winx64\\bin
注意,此时可以以任意一个密码登陆也可以以一个空密码登陆 MySQL,
登陆之后你就可以修改你的root密码喽

🚀 8.2 MySQL 服务器Binlog日志导致磁盘满,怎么办?

1.定时自动清理Binlog日志
mysql>show variables like ‘%expire_logs_days%’; --mysql 5.7
mysql> show variables like ‘%binlog_expire_logs_seconds%’ --mysql8.0
mysql8.0处理方式
mysql 8开始 expire_logs_days 废弃 启用binlog_expire_logs_seconds设置binlog自动清除日志时间
保存时间 以秒为单位;默认2592000 30天
14400 4小时;86400 1天;259200 3天;
mysql> set global binlog_expire_logs_seconds=86400;
mysql5.7处理方式
这个默认是0,也就是logs不过期,可通过设置全局的参数,使他临时生效:
mysql>set global expire_logs_days=10;

2.手动删除Binlog日志
第一步:登陆进入mysql,并使用 show binary logs; 查看日志文件。
mysql>show binary logs;
第二步:查看正在使用的日志文件:show master status;
mysql>show master status;
当前正在使用的日志文件是mysqlhost01-bin.000010,那么删除日志文件的时候应该排除掉该文件。
删除日志文件的命令:purge binary logs to ‘mysqlhost01-bin.000010’;
mysql>purge binary logs to ‘mysqlhost01-bin.000010’;
删除除mysqlhost01-bin.000010以外的日志文件
也可以指定其他文件名,例如mysql-bin.000003。
删除后就能释放大部分空间。

🚀 8.3 MySQL无法创建函数,怎么办?

出现ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL,
or READS SQL报错mysql的设置默认是不允许创建函数
1、更改全局配置
SET GLOBAL log_bin_trust_function_creators = 1;
2、更改配置文件my.cnf,重启服务生效
log-bin-trust-function-creators=1;
mysql> show variables like ‘log_bin_trust_function_creators%’;

以上是关于MySQL八股文连环45问,你能坚持第几问?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle夺命连环25问,你能坚持第几问?

HashMap夺命连环问,你能坚持到第几问?

MySQL夺命16问,你能坚持到第几问?

MySQL夺命10问,你能坚持到第几问?

ThreadLocal源码夺命12问,你能坚持到第几问?

ConcurrentHashMap源码夺命15问,你能坚持到第几问?