面试整理

面试整理
青夢面试整理
MySQL
MySQL为什么采用B+树存储?
MySQL中主要有两个核心的理论:索引和事务 1、索引需要有一个高效的数据结构来进行组织 2、事务中最核心之一的隔离级别 -> 锁+MVCC(多版本并发控制),锁常见问题有死锁,而死锁则与加锁顺序有关,也需要了解数据结构
主要是出于 磁盘访问效率、范围查询性能和稳定性 的考虑。
B+树是为磁盘而生的数据结构,既能减少 I/O,又能兼顾等值和范围查询,是数据库索引的最佳选择
1 | # 磁盘与内存io比较 |
- 磁盘访问效率:B+树是一个更加矮胖的数据结构,它比平衡二叉搜索树更加矮胖,高度就比较低,所以访问磁盘的次数就比较少(通常 2~4 层就能存储上千万行数据)。
- 范围查询、单点查询:所有数据都存放在叶子节点,内节点只存索引,B+树的叶子节点之间通过双向循环链表连接,扫描范围时只需顺序遍历叶子节点;因为内节点不存储实际数据,只存储键和指针,能容纳更多的 key,从而树更“矮胖”,进一步减少磁盘 I/O。而B树数据分布在内节点和叶子节点上。
MySQL事务隔离级别如何实现的?
事务:可以理解成数据库里的“打包操作”:一组 SQL 语句要么全部成功,要么全部失败,不允许中间状态。
1
2
3
4
5
6
7START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE user_id = 1;
UPDATE account SET balance = balance + 100 WHERE user_id = 2;
COMMIT;
-- 事务是数据库中最小的逻辑操作单元,通常包含多个 SQL 操作
-- 表示从用户1转账100元给用户2。如果中间出错,比如第二条语句失败,整个事务就会回滚,数据不会被修改事务的四大特性(ACID)
- 原子性:要么全做,要么全部做
- 一致性:数据前后状态都必须合法
- 隔离性:多人同时操作不会互相干扰
- 持久性:提交后数据永久保存,即使断电池也不丢失
事务的隔离级别是靠:MVCC(版本链+Read View)保证读一致性,锁(行锁、间隙锁、Next-Key锁)保证写隔离性
MySQL是怎么执行一条SQL语句的?
flowchart TD
A[客户端发送SQL] --> B[连接器: 用户认证]
B --> C[解析器: 词法/语法分析]
C --> D[预处理器: 表/字段检查, 权限校验]
D --> E[优化器: 生成执行计划]
E --> F[执行器: 调用存储引擎]
F --> G[存储引擎: InnoDB, B+树, 磁盘I/O]
G --> H[返回结果给客户端]
select、insert、update、delete都会执行查询,因为需要定位到具体的数据行,insert、update、delete统称为DML语句
- 客户端:客户端发送的传输协议一般是TCP/IP
- 连接层:连接器负责账号、密码、权限认证,用以建立TCP长连接、短连接、连接池
- SQL层(Server层):
- 在5.7版本还有一个查村缓存,但在8.0移除了,是KV存储的缓存,key是存储查询语句,由于命中低移除
- 解析器检查SQL是否符合语法(SELECT、FROM、WHERE),生成语法树
- 预处理器解析表明、列名是否合法以及用户读/写权限
- 优化器基于执行成本决定具体的执行计划,如是否走索引、使用哪个索引等
- 执行器调用存储引擎的接口,从磁盘中读取数据
- 存储引擎层:支持多种引擎(InnoDB、MyISAM、Memory等),在创表的时候就会选择存储引擎,默认是InnoDB。InnoDB的大致流程:查Buffer Pool(内存缓存)是否有数据、如果没有,出发磁盘IO,从数据页(默认16KB)加载、利用B+树索引定位数据行、返回结果给执行器
其他
进程和线程的区别,何时使用多线程和多进程?
进程 = 一个公司,有独立的办公楼、资金、部门(资源)。
线程 = 公司里的员工,共享同一个办公楼(内存),但有自己的办公桌(栈)。
进程:定义>程序运行的一个实例,系统资源分配的基本单位,资源>独立的地址空间(代码段、堆、栈、数据段),进程间资源隔离,安全性>进程间相互隔离,崩溃不会影响其他进程(更稳定),通信方式>进程间通信 (IPC):管道、消息队列、共享内存、socket,开销大,适用场景>需要高稳定性、强隔离性(数据库、浏览器多进程)
多进程适用场景:CPU密集型(大量计算、科学计算等)、高可靠性场景(浏览器多进程)、安全/隔离要求高(数据库服务/容器)
线程:定义>进程中的执行单元,是 CPU 调度的基本单位,资源>共享进程的地址空间(代码段、堆、文件描述符等),但有独立的栈和寄存器,安全性>线程共享内存,可能相互影响,一个线程崩溃可能导致整个进程挂掉,通信方式>线程间通信直接读写共享内存,效率高,但需加锁避免竞争,适用场景需要高性能、共享数据方便(Web 服务器、多任务计算)
多线程适用场景:IO密集型(网络请求、磁盘读写等)、频繁共享数据的任务(Web服务器的每个连接)
程序CPU占用率较高,如何排查?
- 定位进程
top/htop查看整体CPU使用率,找出最消耗的进程PID
- 定位线程
ps -mp <PID> -o THREAD,tid,time查看该进程的各个线程的CPU占用pidstat -p <PID> 1实时监控指定进程的CPU占用
- 查看线程堆栈
py-spy top --pid <PID>或py-spy dump抓堆栈,定位具体是哪一段函数,工具如py-spy、line-profiler、cProfile
- 查看日志
- 分析并解决






