MySQL面试必问的5个核心问题(附实战解析)

一、事务的ACID特性到底是啥??

这个问题绝对稳居面试问题排行榜TOP1!!!(重要程度五颗星)很多同学背得滚瓜烂熟,但一被追问就露馅。咱们先看这个经典场景:

-- 转账操作示例
START TRANSACTION;
UPDATE account SET balance = balance - 500 WHERE user_id = 'A';
UPDATE account SET balance = balance + 500 WHERE user_id = 'B';
COMMIT;

**原子性(Atomicity)**就像打包快递(这个比喻超形象!),要么整个包裹成功送达,要么原封不动退回。数据库通过undo log实现回滚能力。

**一致性(Consistency)**是终极BOSS(重要但容易被忽略),它确保数据从一个合法状态转换到另一个合法状态。比如转账前后总额不变,这个要靠应用层和数据库双重保障。

**隔离性(Isolation)**的坑最多!!上次我们项目就遇到个幻读问题——上午查库存10件,下单时突然变成5件,最后发现是其他事务插入了负库存记录(血泪教训啊)。

**持久性(Durability)**靠的是redo log这个神器。突然断电时,重启后数据库会通过redo log把没刷盘的数据重新写入。

二、索引怎么用才能起飞??

先看这个死亡案例(新手必踩坑):

CREATE INDEX idx_name ON user(name); 
SELECT * FROM user WHERE UPPER(name) = 'JOHN'; -- 索引失效!

B+树索引就像字典目录(这个类比绝了),但以下情况会翻车:

  1. 列参与计算(age+1=20)
  2. 使用函数(UPPER(name))
  3. 模糊查询(LIKE ‘%abc’)
  4. 类型转换(字符串转数字)

复合索引的最左前缀原则要牢记!比如索引(a,b,c):

  • ✅能用的:a=1 / a=1 AND b=2
  • ❌没用的:b=2 / c=3 / b=2 AND c=3

有个优化秘诀(一般人我不告诉):用覆盖索引避免回表。比如:

-- 普通查询
SELECT * FROM orders WHERE user_id = 100; -- 需要回表

-- 优化版
SELECT order_id FROM orders WHERE user_id = 100; -- 使用索引覆盖

三、慢查询怎么破??

先记住这个排查口诀(亲测有效):

  1. 开慢查询日志(slow_query_log)
  2. 用EXPLAIN看执行计划
  3. 重点关注type列(最好到ref级别)
  4. 看Extra列有没有Using filesort

最近优化过的一个案例:

-- 优化前(执行时间2.3秒)
SELECT * FROM logs 
WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
ORDER BY user_id DESC 
LIMIT 1000;

-- 优化后(0.2秒!)
ALTER TABLE logs ADD INDEX idx_time_user (create_time, user_id);
SELECT create_time, user_id, action FROM logs 
WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
ORDER BY user_id DESC 
LIMIT 1000;

关键点

  • 避免SELECT *
  • 利用索引排序
  • 控制返回字段
  • 合理使用分页(大数据量用WHERE id > xxx代替LIMIT)

四、锁机制有多重要??

去年我们系统遇到个诡异的bug:用户充值偶尔会重复到账。最后发现是这么写的:

BEGIN;
SELECT balance FROM account WHERE user_id=123 FOR UPDATE;
-- 这里有个外部API调用,耗时2秒!
UPDATE account SET balance = balance + 100 WHERE user_id=123; 
COMMIT;

问题分析

  • 长时间持有行锁会导致并发骤降
  • 外部调用应该放在事务之外
  • 改用乐观锁(版本号控制)更合适

不同隔离级别的锁表现:

  • 读未提交:基本没锁
  • 读已提交:写锁保持到事务结束
  • 可重复读:间隙锁防止幻读
  • 串行化:直接加表锁

五、三大日志怎么选??

binlog(归档日志):

  • 主从复制的核心
  • 支持statement/row/mixed格式
  • 数据恢复的最后防线

redo log(重做日志):

  • 保证持久性
  • 采用循环写入方式
  • crash recovery时重放

undo log(回滚日志):

  • 实现事务回滚
  • 支持MVCC多版本控制
  • 会被定期清理

有个冷知识(面试加分项):刷盘策略怎么选?

  • sync_binlog=0:靠OS自己刷
  • sync_binlog=1:每次commit都刷(最安全但性能差)
  • sync_binlog=N:累积N次刷一次

六、总结与建议

MySQL就像乐高积木(这个比喻绝了),每个模块都要严丝合缝。建议大家:

  1. 用docker起个测试环境,随便搞破坏
  2. 多关注官方文档的版本变化(比如MySQL8.0的窗口函数)
  3. 实操时打开general_log看完整执行过程
  4. 定期用pt-query-digest分析慢日志

最后送大家一句话:读十遍文档不如亲手搞崩一次数据库(真的!故障是最好的老师)。遇到问题别慌,先explain再优化,记住索引不是万能的,但没有索引是万万不能的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值