面试题精讲:数据库
开篇:数据库是后端面试的「敲门砖」
Python 后端开发(无论是 Flask/Django 写 Web 服务、还是爬虫接口对接存储)都完全离不开数据库,据不完全统计,硬核数据库面试题能占到后端面经的 30%-40%。
这篇整理了 7 个最常考、写代码时也最容易踩坑的核心知识点,带点实战视角,不堆干巴巴的定义:
1. 数据库事务 (Transaction)
面试必背 + 实战避坑双项选择
核心就是背 ACID 四特性,但别只会念,要加一句「在 Python 中用 ORM(比如 Django ORM、SQLAlchemy)开启事务更安全,避免手动漏提交/回滚」。
四特性拆解(人话版)
2. 数据库索引与 B+ Tree
灵魂拷问:为什么 MySQL InnoDB 首选 B+ Tree?
二叉树/B-Tree/哈希索引都不行,核心原因围绕「数据库是存磁盘的,磁盘IO是性能杀手」展开。
先踩踩其他索引的坑
- 二叉搜索树/BST:极端情况(比如按顺序存1-10000)会退化成链表,查询时间复杂度O(n)
- 红黑树:虽然是平衡的,但高度太高(存10000条数据要14层左右),磁盘IO次数多
- B-Tree:内部节点也存数据,每个节点能装的索引少,树还是不够矮胖;范围查询要跨层遍历,慢
- 哈希索引:只适合等值查询(
WHERE id=1),范围、排序、模糊查询全跪
B+ Tree 的三大杀招(对应 MySQL 高频考点)
- 磁盘IO代价极低:内部节点全是空壳索引,一个磁盘页(InnoDB 默认 16KB)能装成百上千个索引,树矮胖到只有3-5层,1次查询最多5次磁盘IO
- 查询效率绝对稳定:所有数据都在叶子节点,从根到任意叶子的路径长度完全一致
- 范围/排序查询吊打一切:叶子节点用双向链表串起来了,直接扫链表就行,不用跳回根节点重查
聚集索引 vs 非聚集索引(Python 开发常搞混回表!)
3. Redis 核心原理
灵魂拷问三连:单线程为什么快?数据结构用什么?怎么持久化不丢数据?
Redis 是 Python 后端缓存三剑客(Redis/Memcached/本地缓存)的绝对老大,面试必考!
单线程为什么能吊打多线程的 Memcached?
别再说「Redis 完全是单线程」了——Redis 6.0+ 后台任务(持久化、清理过期键)是多线程的,但命令处理的核心(内存操作+IO多路复用)还是单线程,这是它快的根本:
- 纯内存操作:读写都是在内存里搞,比磁盘IO快10万倍以上
- IO 多路复用(epoll/kqueue):一个线程就能监听成千上万个客户端连接,不用每个连接开一个线程(避免了上下文切换和锁竞争)
- 命令处理的核心无锁:单线程操作内存,根本不需要加锁解锁,效率飙升
高频数据结构(别只会说 String!)
持久化策略(RDB vs AOF vs 混合,主流选混合!)
纯内存操作有个致命缺点:断电/重启数据全丢,所以必须持久化到磁盘:
- RDB(快照):定时(比如 save 900 1)把内存里的所有数据全量压缩成二进制文件存到磁盘
- ✅ 恢复极快(适合备份/迁移)
- ❌ 容易丢数据(最多丢 save 间隔内的所有数据)
- AOF(追加日志):把每个写命令逐行追加到文本文件里(类似 MySQL 的 Binlog)
- ✅ 数据安全性极高(配置 appendfsync always 几乎不丢)
- ❌ 文件越来越大、恢复越来越慢
- 混合持久化(Redis 4.0+,Python 后端默认建议开):RDB 头(全量) + AOF 尾(增量),既有 RDB 恢复快的优点,又有 AOF 数据安全的优点
4. 悲观锁 vs 乐观锁
场景为王:读多写少选乐观,写多读少选悲观!
Python 开发经常会遇到「多个人同时改同一条库存」的问题,这时候就要加锁了。
悲观锁(先锁后用,稳但慢)
- ✅ 绝对不会出现超卖
- ❌ 锁的时间长,并发性能差(只有拿到锁的人能操作)
- 🎯 适用场景:抢票、秒杀(写多读少、并发竞争极其激烈)
乐观锁(假设没人抢,提交时再检查,快但有冲突)
- ✅ 不加锁,并发性能好
- ❌ 冲突率高的时候需要频繁重试,反而更慢
- 🎯 适用场景:修改用户信息、点赞(读多写少、冲突概率低)
5. MVCC (多版本并发控制)
InnoDB 的秘密武器:解决「读-写」冲突的非阻塞读!
如果只有锁,「读-写」操作也会互相阻塞,并发性能会很差,MVCC 就是为了解决这个问题的。
人话版原理
InnoDB 给每行数据加了两个隐式列(不需要手动建):
- 创建时间戳:记录创建/修改这行数据的事务 ID
- 删除时间戳:记录删除这行数据的事务 ID(如果没删除就是 NULL)
同时用 Undo Log(回滚日志) 存了数据的历史版本链表。
两种读操作(Python 开发要注意!)
- 快照读(普通 SELECT,99% 的情况用的是这个):不加锁,读的是 Undo Log 里的历史版本,不会阻塞写操作,也不会被写操作阻塞
- 当前读(INSERT/UPDATE/DELETE,或者加了锁的 SELECT):读的是最新版本,需要加锁
6. 存储引擎:MyISAM vs InnoDB
Python 后端直接无脑选 InnoDB!除非…
MySQL 5.5 之后默认就是 InnoDB 了,但 MyISAM 偶尔还会在老项目里看到,背清楚对比表就行。
7. Elasticsearch (ES) 搜索深度解析
当 MySQL 的模糊搜索慢到爆炸时,试试 ES!
ES 是基于 Lucene 的分布式全文检索服务器,Python 开发常用它做电商商品搜索、日志分析、实时监控。
核心杀招:倒排索引 (Inverted Index)
MySQL 的模糊搜索(LIKE "%手机%")需要全表扫描,ES 靠倒排索引把搜索速度提升了几个数量级:
比如搜索「苹果手机」,直接查倒排索引里的「苹果」和「手机」的文档ID列表,取交集([1])就行,1秒都不到。
🚀 后续避坑建议
这一章跳了 Redis 和 ES,没讲太细。在 Python 后端面试中,Redis 的缓存雪崩、穿透、击穿是「必考题中的必考题」,我可以单独给你写一篇「Redis 三兄弟避坑指南」,附 Python 代码示例,要不要?

