当前位置: 首页 > news >正文

每日学习Java之一万个为什么?[MySQL面试篇]

分析SQL语句执行流程中遇到的问题

  • 前言
  • 1 MySQL是怎么在一台服务器上启动的
  • 2 MySQL主库和从库是同时启动保持Alive的吗?
  • 3 如果不是主从怎么在启动的时候保证数据一致性
  • 4 ACID原则在MySQL上的体现
  • 5 数据在MySQL是通过什么DTO实现的
  • 6 客户端怎么与MySQL Server建立连接,有哪些建立连接的方式,默认是什么,可以选什么,有哪些应用场景
  • 7.SQL组件接受的SQL是什么形式?为什么单一一条SQL不做任何处理就被MySQL认为是一个事务?
  • 8.查询后的结果是由哪个组件以什么形式返回?
  • 9.解析器是怎么解析的,解析器会调用API吗?
  • 10.优化器是怎么优化的?会调用API吗?
  • 11.SQL报错机制会在哪些区域出现?以什么形式发给客户端?以什么形式写到哪个日志中?
  • 12.执行器本质上是什么?
  • 13 MySQL内部有哪些线程?怎么分类?
  • 14 MySQL进程包含哪些内容
  • 15 执行器会将sql提交给引擎还是调用引擎,又是怎么调用的
  • 16 buffer pool区域中的数据页有多少,以什么结构存储,脏页呢?
  • 17 buffer pool 中的数据页怎么更新的,淘汰后的数据页由谁清理
  • 18 后台线程对脏页刷盘是怎么实现的
  • 19 sql语句中加锁在哪个部分实现的
  • 20 事务在engine中怎么实现
  • 21 MVCC怎么实现
  • 22 redolog分为哪几块内容?有什么作用
  • 23 binlog呢
  • 24 undolog 呢
  • 25 数据写磁盘怎么实现的,怎么传输的,怎么保证一致性的
  • 26 MySQL断开连接可以从线程和客户端区分吗
  • 27 MySQL进程结束会执行哪些持久化操作

前言

面试想要过关斩将,你就必须扪心自问,问得越多问的越细,才能披荆斩棘。盔甲若是漏洞百出,不被戳死才怪。

下列问题为作者提出,回答搜集而来。
由于作者并没有系统化从零开始学习MySQL,所以可能某些非常基础的问题并不了解。

欢迎读者留言比较重要的基础,wink👍

1 MySQL是怎么在一台服务器上启动的

  • MySQL通过配置文件:my.cnf my.ini 来指定各种参数,如端口号、数据目录等。
  • 初始化数据库:首次启动的时候,MySQL需要初始化系统表(这里指定的是系统表空间吗)
  • 启动系统,生成日志

2 MySQL主库和从库是同时启动保持Alive的吗?

为了实现数据同步,通过binlog+并行复制维持数据一致性,主库应该首先启动并正常运行,然后从库再启动并连接到主库。

3 如果不是主从怎么在启动的时候保证数据一致性

  • 如果不是主从库,没法保证,可以自己设置一些通信维护。
    如果没有同时启动,其实无所谓。
  • 保证数据一致性,主从之间首先需要通信,分为三类异步、同步、半同步。由于是主库写日志,等待从库响应。所以主库到底等不等从库是一个影响性能的问题。异步-半同步-同步,一致性会越来越高,期望响应时间越来越长。(那么这里的sql写日志都是事务写进去的吗)
  • 一句话概括:主库提交会写binlog,会由一个dump线程监听binlog文件的变更,如果有更新会推送更新时间到从库,从库接收到事件后会拉取数据,有一个IO线程将binlog传过来的数据写到自己的relaylog中,慢慢消化。所以,我们先更新的是事务语句,至于执行则是慢慢来。
  • 5.6库级别并行复制:
  • 5.7 Group Commit 级别 并行复制
  • logical_clock 逻辑时钟复制
  • Write Set复制

4 ACID原则在MySQL上的体现

  • A:MySQL使用BEGIN /COMMIT /ROLLBACK 来管理事务
  • C:通过约束和触发器确保数据库的状态始终符合预期
  • I:支持四种隔离级别,读未提交,读已提交,可重复读,串行化,通过锁定机制和MVCC实现
  • D:一旦事务提交,数据就会永久保存,即使发生系统崩溃也不会丢失。MySQL使用重做日志 和 双写缓冲区来实现持久性

5 数据在MySQL是通过什么DTO实现的

6 客户端怎么与MySQL Server建立连接,有哪些建立连接的方式,默认是什么,可以选什么,有哪些应用场景

  • TCP IP 通过网络地址和端口连接到MySQL服务器,适用于远程连接
  • Unix Socket连接:在本地Linux/Unix系统上,可以通过Unix域套接字连接到MySQL服务器。这种方式比TCP IP更快,因为它避免了网络层的开销
jdbc:mysql://database_name?socket=/temp/mysql.sck
  • 命名管道:仅适用于win 本地连接

  • 共享内存:另一种win特有的连接方法

  • 默认使用TCP IP

7.SQL组件接受的SQL是什么形式?为什么单一一条SQL不做任何处理就被MySQL认为是一个事务?

MySQL接收到的SQL是标准的SQL语句,通常以文本的形式发给服务层

在MySQL中,默认情况下,每条单独提交的SQL语句都被视为一个独立的事务。这是因为autocommit模式下,每条语句执行完毕后会自动提交事务。如果autocommit被关闭,需要显式的 使用 BEGIN 和 COMMIT 提交事务

8.查询后的结果是由哪个组件以什么形式返回?

执行器也就是sql线程生成结果集,通过网络协议返回给客户端

  • 执行器:执行查询并生成结果集 MYSQL_RES结构
  • 网络层:将结果集打包成适当的格式(如二进制或文本),并通过连接通道返回给客户端。
typedef struct st_mysql_res
{
my_ulonglong row_count;
unsigned int field_count,current_field;
MYSQL_FIELD *fields;
MYSQL_DATA *data;
MYSQL_ROWS *data_cursor;
MEM_ROOT field_alloc;
MYSQL_ROW row;
MYSQL_ROW current_row;
unsigned long *lengths;
MYSQL *handle;
my_bool eof;
}MYSQL_REStypedef struct st_mysql_rows 
{struct st_mysql_rows *next;	//列表的行MYSQL_ROW data;
} MYSQL_ROWS;   //mysql的数据的链表节点。可见mysql的结果集是链表结构typedef struct st_mysql_data 
{my_ulonglong rows;unsigned int fields;MYSQL_ROWS *data;MEM_ROOT alloc;
} MYSQL_DATA;   // 数据集的结构typedef struct st_mysql_field 
{char *name;					// 列名称 char *table;	                //如果列是字段,列表char *def;	                //默认值(由mysql_list_fields设置)enum enum_field_types type;	//类型的字段。Se mysql_com。h的类型unsigned int length;	        //列的宽度unsigned int max_length;	    //选择集的最大宽度unsigned int flags;	        //Div标记集unsigned int decimals;	    //字段中的小数位数
} MYSQL_FIELD;  //列信息的结构typedef struct st_used_mem      //结构为once_alloc
{	struct st_used_mem *next;   	//下一个块使用unsigned int left;	        //记忆留在块unsigned int size;	        //块的大小
} USED_MEM;     //内存结构typedef struct st_mem_root 
{USED_MEM *free;USED_MEM *used;USED_MEM *pre_alloc;unsigned int	min_malloc;unsigned int	block_size;void (*error_handler)(void);
} MEM_ROOT;  //内存结构

可以看到MySQL是用C++/C 开发的

9.解析器是怎么解析的,解析器会调用API吗?

  • 词法分析:将SQL语句分解为一个个token

  • 语法分析:tokens转换语法树

  • 语义分析

  • 解析器本身并不调用外部API,但他可能会调用内部函数或者模块来完成某些任务,例如:

  • 元数据访问:访问系统表或缓存中的元数据,以验证表和列的存在性。

  • 权限检查:调用权限管理模块,确保用户有足够的权限执行该操作

10.优化器是怎么优化的?会调用API吗?

  • 查询重写:对查询初步重写,以简化查询结构
  • 统计信息收集:收集表的统计信息(例如行数、索引选择性等),用于生成最优执行计划。
  • 生成候选计划:基于不同的访问路径(如全表扫描、索引扫描),生成多个候选执行计划(生成策略?)
  • 选择最佳计划:评估每个候选计划的成本(评估算法?),选择成本最低的计划作为最终执行计划
  • 优化器内部统计信息模块:获取表的统计信息(包含什么?)
  • 代价模型:计算成本 (理论支持?)
  • 访问路径模块:确定可用的访问路径(索引、表扫描等)

11.SQL报错机制会在哪些区域出现?以什么形式发给客户端?以什么形式写到哪个日志中?

报错机制出现的区域:

  • 解析阶段:SQL语法错误或未知表/列名
  • 优化阶段:无法生成有效的执行计划
  • 执行阶段:运行时错误,如违反约束、超时等
  • 网络传输阶段:连接断开或其他通信错误

发给客户端的形式:

  • 错误代码:一个唯一的数字标识。
  • 错误消息:详细的描述信息,帮助理解错误原因。
{"code":1054,"message":"Unknown column 'nonexistent_column'in 'field list'"
}

写入日志的形式:

  • 错误日志:记录所有严重的错误和警告,默认位于/var/log/mysql/error.log 或安装目录下的data文件夹中。
  • 慢查询日志:记录执行时间超过阈值的查询,默认位于/var/log/mysql/slow-query.log
2025-02-27T11:41:23.123456Z 0 [ERROR] [MY-01054] Unknown column 'nonexistent_column' in 'field list'

12.执行器本质上是什么?

执行器是MySQL查询处理过程中实际执行查询计划的部分。它根据优化器生成的执行计划,调用存储引擎接口来访问和修改数据。

执行器的主要职责:

1.物理操作执行:根据执行计划中的物理操作(如表扫描、索引查找等)执行相应的数据库操作。
2.数据获取与处理:从存储引擎中获取数据,并进行必要的过滤、排序、聚合等操作。
3.结果集生成:将处理后的数据组织成结果集,准备返回给客户端。

执行器的工作流程:
1.初始化执行计划:加载执行计划并准备执行环境。
2.执行物理操作:按顺序执行各个物理操作步骤。
3.返回结果

13 MySQL内部有哪些线程?怎么分类?

1.主线程(Main Thread)

  • 职责:负责启动和管理其他的线程
  • 实例:mysql进程的主线程

2.连接处理线程(Connection Threads)

  • 职责:处理客户端连接请求,每个客户端连接对应一个独立的线程
  • 实例:thd线程对象,用于处理每个客户端连接

3.后台线程(Background Threads)

  • 职责:执行各种后台任务,如日志刷新、数据页刷盘等。
  • 示例:InnoDB缓冲池线程:负责缓冲池管理和脏页刷盘。Binlog Dump线程:监听binlog 发送给从库。Purge线程:负责清理不再需要的undo日志

4.IO线程(I/O Threads)

  • 职责:处理与存储设备的IO操作
  • 示例:Redo Log线程:负责写入重做日志。 Binlog线程:负责写入二进制日志。

5.事务处理线程(Transaction Handing Threads)

  • 职责:管理事务的开始、提交和回滚操作。
  • 示例:事务管理线程,负责协调事务的状态。

14 MySQL进程包含哪些内容

MySQL进程(mysqld)包含多个组件和模块,主要分为以下几个部分:

  • 1.服务器核心 Server Core

    1. 存储引擎 Strorage Engines
  • 3.缓存和缓冲区(Caches and Buffers)

    • Buffer Pool:用于缓存数据和索引数据。
    • Query Cache:缓存查询结果以提高查询效率(读缓存已被移除)
  • 日志系统 (Logging System)

    • Binlog:用于主从复制和数据备份,记录所有更改操作。
    • Undo Log:用于事务回滚,记录事务的反向操作
    • Redo Log:用于崩溃恢复,记录所有未提交的事务
  • 网络层(Network Layer)

    • 处理客户端连接、数据传输和协议解析。
  • 安全管理(Security Management)

    • 执行各种后台任务,如日志刷新、数据页刷盘等。

15 执行器会将sql提交给引擎还是调用引擎,又是怎么调用的

执行器会通过调用存储引擎的接口来执行具体的数据库操作

调用方式:

  • 接口调用:执行器通过调用存储引擎提供的接口(如InnoDB的API)来执行具体的操作。
  • 物理操作执行:根据优化器生成的执行计划,执行器调用相应的存储引擎接口来访问和修改数据。

16 buffer pool区域中的数据页有多少,以什么结构存储,脏页呢?

数据页数量:

  • 大小可配置:Buffer Pool的大小可以通过配置文件中的innodb_buffer_pool_size参数设置,默认值通常为系统内存的70%-80%。
  • 每页大小:默认情况下,每页大小为16KB。

存储结构:

  • LRU链表:Buffer Pool 使用LRU(Least Recently Used)链表来管理数据也。最近使用的页面位于链表前端,较少使用的页面位于链表末端。
  • Flush链表:脏页(已修改但尚未写入磁盘的页面)会被放入Flush链表中,等待刷盘

脏页:

  • 定义:脏页是指已经被修改但还写回到磁盘的数据页。
  • 存储位置:脏页同样存储在Buffer Pool中,并被标记为脏页。
  • 管理:脏页通过Flush链表管理,定期或在特定条件下(如内存不足或打到一定阈值)被刷回磁盘。

17 buffer pool 中的数据页怎么更新的,淘汰后的数据页由谁清理

数据页更新:

  • 读取当前数据页:当需要访问某个数据页时,如果该页不在Buffer Pool中,则从磁盘加载到Buffer Pool。
  • 修改数据页:对数据页进行修改后,将其标记为脏页。
  • 写回磁盘:脏页会在适当的时候(如内存不足或达到一定的阈值)通过后台线程写回到磁盘。

淘汰后的数据页清理:

  • LRU链表:当Buffer Pool 满时,使用LRU算法淘汰最近最少使用的页面

  • 清理过程:

    • 如果被淘汰的页面是干净的(未修改),可以直接丢弃。
    • 如果被淘汰的页面是脏页,则必须先将其写回磁盘(通过Flush链表管理)。

18 后台线程对脏页刷盘是怎么实现的

后台线程通过以下几种机制实现脏页的刷盘:
1.定时刷盘:

  • InnoDB自动刷新:InnoDB会定期检查脏页的比例,如果超过设定的阈值(如innodb_max_dirty_pages_pct),则触发自动刷新操作。

2.后台线程:

  • Page Cleaner线程:负责将脏页写回到磁盘。它会定期检查Flush链表中的脏页,并将这些脏页回到磁盘。

3.事务提交:

  • 同步刷盘:在某些情况下(如事务提交),为了保证数据一致性,需要立即刷盘。此时会调用fsync()函数确保数据已经写入磁盘。

4.内存压力:

  • 当Buffer Pool内存不足时,会优先淘汰脏页,并将其写回磁盘。

19 sql语句中加锁在哪个部分实现的

SQL语句的加锁操作主要在执行器和存储引擎中实现:

1.解析阶段:

  • 解析器解析SQL语句,识别出需要加锁的对象(如表、行等)

2.执行器:

  • 执行器根据解析结果,在执行过程中调用存储引擎的加锁接口,对相关对象加锁。

3.存储引擎:

  • 存储引擎实现具体的加锁机制。例如,InnoDB支持行级锁(共享锁,排他锁)和表级锁。
SELECT * FROM users WHERE id = 1 FOR UPDATE;

执行器在执行这条查询时,会调用InnoDB的加锁接口,对users表中id=1的行加排它锁

20 事务在engine中怎么实现

事务在存储引擎中的实现主要包括以下几个方面:

1.事务管理器:

  • 负责事务的生命周期,包括开始、提交、回滚。

2.日志系统:

  • Redo Log:记录所有未提交的事务操作,用于崩溃恢复。
  • Undo Log:记录事务的反向操作

3.并发控制:

  • MVCC(多版本并发控制):支持高并发下的读写操作,避免锁冲突
  • 锁机制:提供行级锁和表级锁,确保事务的隔离性。

4.持久化:

  • 双写缓冲区(Doublewrite Buffer):确保数据页在写入磁盘时的一致性。
  • 刷盘操作:通过后台线程定期将脏页协会到磁盘里。

21 MVCC怎么实现

MVCC,通过维护数据不同的版本来支持高并发下的读写操作。其主要实现机制如下:

  • 隐藏列:每个数据行包含两个隐藏列:DB_TRX_ID 事务ID DB_ROLL_PTR 指向undo的指针。
  • 快照读:读操作(如SELECT)不会阻塞写操作,而是读取数据的历史版本。读操作会根据当前事务的Read View来决定读取哪个版本的数据
  • 写操作:写操作会在新版本的数据上进行操作,并记录undo日志以便回滚。
  • Undo日志:记录事务的反向操作,用于事务回滚和旧版本构建

假如有一个事务在时间点T1插入一条记录,另一个事务B在时间点T2更新了该记录。事务C在T3时间点进行读取操作时,会读取到T2时间点之前的数据版本。

22 redolog分为哪几块内容?有什么作用

Redo Log 是 InnoDB 存储引擎用于崩溃恢复的日志系统,其主要分为以下几个部分:

  • 1.Log Blocks:

    • Redo Log被划分为多个固定大小的块(通常是512字节),每个块称为一个 Log Block。
  • 2.Log Sequence Number(LSN):

    • 每条日志记录都有一个唯一的LSN,表示日志记录的顺序号。
  • 3.Checkpoint

    • Checkpoint 是 Redo Log中的一个特殊标记,表示已成功写入磁盘的数据页。它用于加速崩溃恢复的过程。
  • 崩溃恢复:在MySQL崩溃重启时,通过Redo Log恢复未完成的事务,确保数据的一致性。

  • 提高性能:通过批量写入Redo Log,减少频繁的磁盘IO操作。

23 binlog呢

主要用于主从复制和数据备份。

  • 事件类型:

    • Query Event:记录SQL查询语句。
    • Row Event:记录行级别的变更。
    • XID Event:记录事务提交信息。
  • 格式:

    • Statement-Based Logging:记录SQL语句。
    • Row-Based Logging : 记录每一行的变化。
    • Mixed-Based Logging :混合使用Statement和Row格式。

24 undolog 呢

Undo Log 是 InnoDB 存储引擎用于事务回滚和MVCC 的日志系统。其主要分为以下几个部分:

  • 1.Undo Segment:每个事务分配一个Undo Segment,用于记录该事务的所有Undo日志。

  • 2.Undo Record:每条Undo日志记录一次事务的反向操作,用于回滚和旧版本数据的构建。

  • 事务回滚:在事务回滚时,通过Undo Log 将数据恢复到事务开始前的状态。

  • MVCC:提供历史版本的数据,支持高并发下的操作。

25 数据写磁盘怎么实现的,怎么传输的,怎么保证一致性的

数据写磁盘的实现:

  • 1.Buffer Pool:数据首先写入Buffer Pool,而不是直接写入磁盘。
  • 2.Dirty Page:修改后的数据页标记为脏页,等待后续刷盘操作。
  • 3.后台线程:通过后台线程定期将脏页写回磁盘。

数据传输:

  • 异步写入:大多数情况下,数据写入磁盘是异步的,以提高性能。
  • 同步写入:在某些情况下(如事务提交),需要确保数据已经写入磁盘,此时会调用fsync()函数。

保证一致性:

  • Redolog:记录所有未提交的事务操作,用于数据恢复。
  • 双写缓冲区:确保数据页在写入磁盘时的一致性。
  • 两阶段提交:在分布式环境中,使用两阶段提交协议,确保事务的原子性和一致性。

26 MySQL断开连接可以从线程和客户端区分吗

线程角度:
线程终止:MySQL 服务器端会终止对应的连接线程,并释放相关的资源。
日志记录:断开连接的信息会被记录到错误日志中。
客户端角度:
异常处理:客户端应用程序需要捕获连接断开的异常,并进行相应的处理(如重新连接)。
超时机制:客户端可以通过设置超时参数(如 wait_timeout 和 interactive_timeout)来控制连接的有效期。

27 MySQL进程结束会执行哪些持久化操作

MySQL 进程结束时会执行一系列持久化操作,以确保数据的一致性和完整性:

Redo Log 刷盘:
将所有未提交的事务操作写入 Redo Log,确保在崩溃恢复时能够恢复这些事务。
Dirty Page 刷盘:
将 Buffer Pool 中的所有脏页写回到磁盘,确保数据的一致性。
Binlog 刷盘:
将 Binlog 中的所有更改操作写入磁盘,确保主从复制和数据备份的一致性。
Checkpoints:
创建 Checkpoint,标记已成功写入磁盘的数据页,加快崩溃恢复的速度。
关闭存储引擎:
关闭所有存储引擎实例,释放相关资源。
日志记录:
记录进程结束的相关信息到错误日志中,便于后续排查问题。


http://www.mrgr.cn/news/92619.html

相关文章:

  • ubuntu22.04安装docker engine
  • 【AIGC系列】3:Stable Diffusion模型原理介绍
  • 记一次高并发下导致的数据库死锁解决方案
  • AWS ALB 实现灰度验证指南:灵活流量分配与渐进式发布
  • 使用schemdraw-markdown库绘制电路图
  • linux中安装部署Jenkins,成功构建springboot项目详细教程
  • 【Stable Diffusion】AnimatedDiff--AI动画 插件使用技巧分享;文生视频、图生视频、AI生成视频工具;
  • 【uniapp】在UniApp中实现持久化存储:安卓--生成写入数据为jsontxt
  • or-tools编译命令自用备注
  • postgresql postgis扩展相关
  • 第002文-kali虚拟机安全与网络配置
  • vue3学习
  • WiseFlow本地搭建实录---保姆教程
  • 跨AWS账户共享SQS队列以实现消息传递
  • Rt-thread源码剖析(1)——内核对象
  • 自然语言处理:稀疏向量表示
  • 智慧校园平台在学生学习与生活中的应用
  • [Lc优选算法] 双指针 | 移动零 | 复写零 | 快乐数
  • MySQL 创建指定IP用户并赋予全部权限(兼容8.0以下及8.0以上版本)
  • NFC拉起微信小程序申请URL scheme 汇总