面试题-复合
MySQL
一、基础概念与存储引擎
-
ACID 特性及实现原理
- 原子性:通过 Undo Log 实现回滚操作,确保事务要么成功要么失败;
- 持久性:依赖 Redo Log 在事务提交前持久化日志,保证数据不丢失;
- 隔离性:通过锁机制和 MVCC(多版本并发控制)实现事务间的隔离。
-
InnoDB 与 MyISAM 的核心区别
- 事务支持:InnoDB 支持 ACID 事务,MyISAM 不支持;
- 锁粒度:InnoDB 支持行级锁,MyISAM 仅支持表级锁;
- 外键与 MVCC:InnoDB 支持外键约束和 MVCC,MyISAM 不支持;
- 适用场景:InnoDB 适合高并发写操作,MyISAM 适合读密集型场景。
二、索引与查询优化
-
B+ 树索引的优势
- 范围查询:叶子节点通过链表连接,支持高效范围查询;
- 稳定性:非叶子节点仅存储键值,树高度较低,查询路径稳定;
-
覆盖索引与最左前缀原则
- 覆盖索引:查询字段全在索引中时,避免回表操作(如
SELECT a,b FROM table WHERE a=1
); - 最左前缀原则:联合索引
(a,b,c)
需从最左列开始使用,否则索引失效;
- 覆盖索引:查询字段全在索引中时,避免回表操作(如
-
EXPLAIN 关键字段解析
- type:
const
(主键查询) >range
(范围索引) >index
(全索引扫描) - Extra:
Using index
(覆盖索引)、Using temporary
(使用临时表)
- type:
三、性能优化实践
-
慢查询优化方法
- 日志分析:开启
slow_query_log
记录执行时间过长的 SQL38 - 避免全表扫描:优化 WHERE 条件、添加合适索引67
- 日志分析:开启
-
分页查询优化
- 深度分页:使用覆盖索引 + 延迟关联(如
SELECT * FROM table WHERE id > 1000 LIMIT 10
)
- 深度分页:使用覆盖索引 + 延迟关联(如
四、典型陷阱与注意事项
-
隐式类型转换
- 字符串字段未加引号(如
WHERE id = '100'
vsWHERE id = 100
)会导致索引失效;
- 字符串字段未加引号(如
-
索引失效场景
- 在索引列上使用函数(如
WHERE YEAR(create_time)=2025
); - 使用
!=
或<>
运算符
- 在索引列上使用函数(如
Redis
5 种基本数据类型及场景
- String:计数器、分布式锁、缓存(如
INCR
实现 UV 统计) - Hash:存储对象属性(如用户信息)
- List:消息队列(
LPUSH
+BRPOP
实现阻塞队列) - Set:标签系统、共同好友(交集操作)
- ZSet:排行榜(
ZRANGE
查询 TopN)
持久化
缓存问题与解决方案
-
缓存穿透
- 现象:大量请求查询不存在的数据(如恶意攻击)
- 解决:
- 布隆过滤器拦截非法 Key
- 缓存空值(需设置较短过期时间)
-
缓存击穿
- 现象:热点 Key 过期瞬间高并发请求压垮数据库
- 解决:
- 互斥锁(如
SETNX
实现分布式锁) - 逻辑过期(Value 中存储过期时间,异步刷新)
- 互斥锁(如
-
缓存雪崩
- 现象:大量 Key 同时过期或 Redis 宕机
- 解决:
- 随机化 Key 过期时间(如基础过期时间 + 随机偏移量)
- 集群高可用(主从+哨兵)
Golang
一、基础语法与类型系统
-
make
和new
的区别make
:初始化引用类型(slice
、map
、channel
),返回已初始化的数据结构引用new
:分配内存并返回指针,适用于值类型(如结构体),返回未初始化的内存指针
// make 示例 s := make([]int, 0) // 初始化空切片 m := make(map[string]int) // 初始化空 map // new 示例 p := new(int) // 返回 *int 指针,默认值为 0
-
数组与切片的区别
- 数组:固定长度,长度是类型的一部分(如
[5]int
) - 切片:动态长度,底层引用数组片段,包含
ptr
(数组指针)、len
(长度)、cap
(容量)
slice := []int{1, 2, 3} // 切片可动态扩容
- 数组:固定长度,长度是类型的一部分(如
-
字符串与
[]byte
转换是否产生内存拷贝- 直接转换(如
[]byte(str)
)会触发内存拷贝;通过unsafe
包可实现零拷贝(但需谨慎使用)
- 直接转换(如
二、并发与协程
-
主协程等待子协程完成的方法
-
sync.WaitGroup
:通过Add()
、Done()
、Wait()
实现协程同步
var wg sync.WaitGroup for i := 0; i < 3; i++ {wg.Add(1) go func() { defer wg.Done() // 业务逻辑 }() } wg.Wait() // 阻塞直到所有协程完成
-
-
Channel
的特性与使用场景- 无缓冲通道:同步通信,发送和接收需配对出现
- 有缓冲通道:异步通信,缓冲区满时发送阻塞
- 已关闭通道:接收操作返回零值,发送触发 panic
三、数据结构与内存管理
-
Map 的初始化与扩容
- 未初始化:值为
nil
,直接操作会触发 panic - 初始化:通过
make(map[string]int, 10)
预分配容量以减少扩容次数 - 扩容规则:当元素数量超过负载因子(默认 6.5)时触发哈希表扩容
- 未初始化:值为
-
Slice 的底层实现与扩容机制
- 底层结构:包含指向数组的指针、长度和容量7
- 扩容规则:
- 容量 <1024:双倍扩容
- 容量 ≥1024:按 1.25 倍扩容(考虑内存对齐)