银行技术面数据库基础:事务、隔离级别与三大范式
- 轮次
- 技术面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 事务是什么?为什么一组操作要打包成事务?
- ACID 分别指什么?它们之间是平级关系吗?
- 并发环境下会出现哪些一致性问题?脏读、不可重复读、幻读分别是什么表现?
- 不可重复读和幻读的区别在哪?
- 事务隔离有哪几个级别?每个级别分别解决了哪些问题?
- MySQL 的 InnoDB 存储引擎默认是可重复读,它是怎么实现的?
- 三大范式是什么?设计不规范的表会出现哪些问题?
- 第一范式、第二范式、第三范式各自要求什么?
- SQL 和 NoSQL 的区别是什么,各自适合什么场景?
《参考解析》
-
事务与 ACID:事务是一组要么全做、要么全不做的操作。转账是最典型的例子:A 扣款和 B 入账必须同时成立,中途失败要整体回滚,否则钱会凭空消失或凭空产生。ACID 里,原子性由 undo log 保证回滚能力,持久性由 redo log 保证提交后不丢,隔离性由锁与 MVCC 共同实现,而一致性是前三者共同作用的结果、不是独立的一项。所以四者不是平级的并列关系:无并发时只要满足原子性就自然满足一致性;有并发时还要靠隔离性才能守住一致性。
-
并发一致性问题:脏读是读到了别的事务尚未提交的数据,对方一回滚,读到的就是从未存在过的值。不可重复读是同一事务内两次读同一行,中间被别的事务更新了,导致前后结果不同。幻读是同一事务内两次按同样条件查一段范围,中间被别的事务插入或删除,导致行数变了。区分口径很清晰:不可重复读盯的是同一行的值被改,幻读盯的是结果集的行数增减。此外还有丢失修改:两个事务同时读同一余额再各自写回,后写的覆盖先写的。
-
隔离级别与取舍:读未提交三个问题都挡不住;读已提交能挡脏读;可重复读能挡脏读和不可重复读、但幻读仍可能发生;可串行化全挡,代价是并发度几乎归零。工程上一般停在读已提交或可重复读:前者并发好但要求业务容忍同一事务内的读值漂移,后者一致性更好但锁与版本链开销更大。判断依据是”这个业务能不能接受同一事务内读到不同结果”,而不是哪个级别更高级。
-
InnoDB 可重复读的实现:读靠 MVCC,写靠锁。每行记录里藏有事务版本信息,配合 undo log 版本链和 ReadView,读操作在事务开始时确定可见性快照,因此后续读到的仍是同一版本。幻读则用间隙锁(Next-Key Lock)在可重复读级别下额外拦住范围内的插入,这也是可重复读比读已提交强的地方——它不是靠读快照”看不见”新行,而是直接不让新行插进来。
-
三大范式:第一范式要求每列都是不可再分的原子值;第二范式在满足第一范式的前提下,要求非主属性完全函数依赖于主键,不能只依赖联合主键的一部分;第三范式在前两条之上,要求非主属性之间不能有传递依赖。不规范设计的代价可以按增删改查记:信息冗余(学生信息随选课重复多次)、插入异常(还没选课就没法录入学生)、删除异常(停开一门课把学生也删没了)、更新异常(改一处课程名要改多处、漏改就不一致)。拆表是解法,但拆到极致会带来更多 join,实际设计常在范式与查询性能之间折中。
-
SQL 与 NoSQL:SQL 数据库强在事务、约束和复杂关联查询,数据一致性由数据库兜底,适合订单、账务这类不能出错的核心数据;NoSQL 强在水平扩展和灵活 schema,适合日志、埋点、缓存、文档类数据。选型看的是”这笔数据需不需要强一致与多表关联”,而不是”哪个更新更时髦”——银行场景里核心账务几乎必然留在关系型数据库上。