文章目录
一、基础概念三连击(必考题!)
1. 事务隔离的"套娃"现象
事务隔离级别就像俄罗斯套娃(没想到吧?),从宽松到严格依次是:
- 读未提交(Read Uncommitted):能看到别人没提交的数据(容易脏读)
- 读已提交(Read Committed):只能看到提交后的数据(解决脏读,但可能有不可重复读)
- 可重复读(Repeatable Read):同事务多次读取结果一致(MySQL默认级别!)
- 串行化(Serializable):完全隔离,性能最差但最安全
面试官最爱问:“可重复读怎么解决幻读?” 这时候别慌,记住MVCC(多版本并发控制)这个法宝!通过undo log版本链实现快照读,配合Next-Key Lock防止幻写,这才是标准答案姿势~
2. 索引的七十二变
B+树索引是MySQL的看家本领(划重点!),但你知道这些隐藏玩法吗?
- 联合索引的"最左匹配原则":就像电话号码区号优先,
(a,b,c)索引能查a、ab、abc,但查b或c就抓瞎 - 覆盖索引的妙用:如果索引包含所有查询字段,直接不用回表(性能提升10倍不是梦!)
- 索引下推(ICP):5.6版本后的黑科技,能在存储引擎层提前过滤数据(减少回表次数)
举个真实案例:某电商平台商品表500万数据,WHERE category=3 AND price>100查询耗时800ms。加上(category,price)联合索引后,直接降到50ms,这就是索引的力量!
二、高阶优化三板斧(拉开差距的关键)
1. EXPLAIN执行计划解读
看懂EXPLAIN输出比会写SQL更重要!几个关键指标:
- type列:从好到坏排序 system > const > eq_ref > ref > range > index > ALL
- Extra列注意:
Using filesort:需要额外排序(考虑加索引)Using temporary:用了临时表(GROUP BY无索引时常见)Using index condition:用了索引下推
2. 慢查询优化实战
遇到慢SQL别急着加索引,先做三件事:
- 用
SHOW PROFILE看时间消耗分布 - 检查是否加载了多余字段(特别是TEXT/BLOB)
- 查看是否隐式类型转换(比如字符串字段用数字查询)
曾经处理过一个诡异案例:WHERE mobile=13800138000查询缓慢,结果发现mobile字段是varchar类型!改成WHERE mobile='13800138000'后速度提升20倍,血泪教训啊!
3. 分页查询的禁忌与突破
LIMIT 100000,10为什么会慢?因为它要遍历前100010行!试试这两种方案:
-- 方案1:子查询分页
SELECT * FROM table WHERE id >= (SELECT id FROM table ORDER BY id LIMIT 100000,1) LIMIT 10
-- 方案2:游标分页(适合连续翻页)
SELECT * FROM table WHERE id > 100000 ORDER BY id LIMIT 10
三、刁钻问题拆招技巧(压力测试必备)
1. 死锁场景模拟
面试官可能会让你手写死锁SQL,记住这个经典组合:
-- 事务1
BEGIN;
UPDATE account SET balance=balance-100 WHERE id=1;
UPDATE account SET balance=balance+100 WHERE id=2;
-- 事务2(相反顺序)
BEGIN;
UPDATE account SET balance=balance-100 WHERE id=2;
UPDATE account SET balance=balance+100 WHERE id=1;
出现死锁后别慌!MySQL会自动检测并回滚代价较小的事务,记得解释如何用SHOW ENGINE INNODB STATUS查看死锁日志。
2. 灵魂拷问:“为什么用自增主键?”
这个问题至少有5个得分点:
- 插入性能高(避免页分裂)
- 减少内存碎片
- 顺序写入对机械硬盘友好
- 提高缓存命中率
- 范围查询效率高
但别忘了补充:“分布式场景下用雪花ID更合适!” 展示你的知识广度~
四、新特性加分项(2024面试风向标)
1. 窗口函数实战
别只停留在理论,现场写个分组排名:
SELECT
salesperson,
region,
sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) as rank
FROM sales_data
2. JSON字段的骚操作
5.7版本后支持的JSON类型,这些用法惊艳面试官:
-- 提取JSON字段
SELECT data->'$.user.name' FROM logs WHERE data->'$.age' > 18
-- 创建虚拟列加速查询
ALTER TABLE logs ADD COLUMN age INT GENERATED ALWAYS AS (data->'$.age');
CREATE INDEX idx_age ON logs(age);
五、避坑指南(来自血泪教训)
- 永远不要在WHERE条件做运算:
WHERE YEAR(create_time)=2024→ 改为范围查询 - 小心NULL值陷阱:
SELECT * WHERE col!=1不会返回NULL记录! - 大表ALTER TABLE要用pt-online-schema-change工具
- 批量插入时用
INSERT INTO ... VALUES (),(),()比多个INSERT快10倍 - 连接池配置不是越大越好!一般建议是(核心数*2 + 磁盘数)
最后送大家一个排查问题的万能口诀:“一慢二看三动手,先查索引再查SQL,执行计划要会瞅,参数配置别乱动”。记住,MySQL优化是门艺术,既要懂原理,更要会实战!
625

被折叠的 条评论
为什么被折叠?



