事务、隔离级别与 MVCC
041 ACID 中的原子性(Atomicity)指的是什么?
难度: 基础
- A. 事务内所有操作要么全部提交生效,要么全部回滚,不允许部分成功
- B. 多个事务的结果必须完全相同,不允许并发
- C. 事务执行时间必须小于 1 秒
- D. 事务内的 SQL 可以跨多个数据库自动同步
查看答案与解析
正确答案A
正确原因: 原子性由 undo log 支持回滚实现,事务失败时撤销全部修改。
关键边界: 外部副作用(消息、接口调用)不会随数据库回滚自动撤销。
错误选项辨析: 保证并发正确性的是隔离性,原子性不承诺并发串行,也不涉及执行时间。
042 脏读(Dirty Read)指的是什么?
难度: 基础
- A. 读到另一个未提交事务修改的数据,该数据可能被回滚
- B. 读到另一个事务已提交但很快又被更新的数据
- C. 读到事务开始前的历史快照数据
- D. 读到主从复制延迟导致的旧数据
查看答案与解析
正确答案A
正确原因: 脏读读到的是未提交数据,若该事务回滚,读到的就是无效数据。
关键边界: InnoDB 默认 REPEATABLE READ 不会出现脏读,READ UNCOMMITTED 才允许。
错误选项辨析: 读到已提交后被更新的数据属于不可重复读,历史快照与复制延迟都不是脏读定义。
043 不可重复读(Non-Repeatable Read)指的是什么?
难度: 基础
- A. 两次读取返回完全相同的行
- B. 同一事务内两次读取同一行,得到不同结果(另一事务已提交更新)
- C. 读取到其他事务未提交的新插入行
- D. 读取时数据库必须加整表锁
查看答案与解析
正确答案B
正确原因: 不可重复读针对行被更新后提交,导致同一事务内两次读取值不同。
关键边界: InnoDB 默认 RR 下普通快照读两次结果一致,幻读针对的是新插入行而非更新。
错误选项辨析: 两次一致是期望行为,未提交插入属于脏读范畴,读取不需要整表锁。
044 幻读(Phantom Read)指的是什么?
难度: 基础
- A. 同一行两次读取的值不同
- B. 同一事务两次范围查询返回的行集合不同(另一事务插入了新行)
- C. 读到未提交事务删除的行
- D. 查询结果自动按主键排序
查看答案与解析
正确答案B
正确原因: 幻读是范围结果集变化,另一事务在区间内插入了新行。
关键边界: RR 下 InnoDB 用间隙锁与临键锁阻止插入,但主要作用于当前读与写操作。
错误选项辨析: 同一行值变化是不可重复读,未提交删除是脏读,排序与幻读无关。
045 InnoDB 的默认事务隔离级别是?
难度: 基础
- A. READ UNCOMMITTED
- B. READ COMMITTED
- C. REPEATABLE READ
- D. SERIALIZABLE
查看答案与解析
正确答案C
正确原因: InnoDB 默认隔离级别是 REPEATABLE READ,与 PostgreSQL 默认 READ COMMITTED 不同。
关键边界: 可通过 SET TRANSACTION 或配置逐会话调整。
错误选项辨析: READ UNCOMMITTED 允许脏读,READ COMMITTED 与 SERIALIZABLE 都不是 InnoDB 默认值。
046 快照读(一致性读)与当前读的区别是?
难度: 基础
- A. 快照读必须等待所有写事务提交才能返回
- B. 当前读不加锁,可被任意并发写覆盖
- C. 快照读基于 ReadView 读历史版本且不加锁;当前读(FOR UPDATE 等)读最新并加锁
- D. 两者读到的数据版本完全相同
查看答案与解析
正确答案C
正确原因: 普通 SELECT 是快照读,通过多版本返回可见快照;锁定读与写语句是当前读。
关键边界: RR 下快照建立于事务首次读,RC 下每条语句建立新快照。
错误选项辨析: 快照读不等待写提交,当前读必须加锁,两者读到的最新程度不同。
047 ReadView 中记录的“活跃事务列表”用于判断什么?
难度: 基础
- A. 判断表中有多少行需要加锁
- B. 记录所有历史 SQL 文本用于审计
- C. 判断磁盘页是否需要刷盘
- D. 判断版本链中哪些版本对当前事务可见(事务是否已提交)
查看答案与解析
正确答案D
正确原因: 通过活跃事务 id 与版本链上的事务 id 比较,决定每个版本对当前事务是否可见。
关键边界: 只有小于最小活跃事务 id 或已提交且不在列表中的版本才可见。
错误选项辨析: 活跃事务列表是 MVCC 可见性判断核心,与加锁行数、SQL 审计、刷盘无关。
048 undo log 在 MVCC 中的作用是?
难度: 基础
- A. 记录重做信息,用于崩溃后恢复数据页
- B. 保存所有 SQL 语句用于审计
- C. 保存索引结构,替代 B+ 树
- D. 保存行的旧版本,形成版本链,供回滚与快照读使用
查看答案与解析
正确答案D
正确原因: undo log 保存旧版本并串联版本链,回滚与快照读都要使用。
关键边界: purge 线程回收不再被任何快照引用的旧版本。
错误选项辨析: 崩溃恢复靠 redo log,SQL 审计靠 general log,索引结构是 B+ 树。
049 MVCC 主要解决了哪些问题?
难度: 进阶
- A. 读不阻塞写、写不阻塞读,配合隔离级别消除脏读等读异常
- B. 彻底消灭死锁,事务无需再等待锁
- C. 让所有事务读写完全串行,无需锁
- D. 消除主从复制延迟
查看答案与解析
正确答案A
正确原因: MVCC 让快照读不加锁,读写并发互不阻塞,并通过可见性规则隔离未提交数据。
关键边界: 写写冲突仍需加锁,死锁仍可能发生。
错误选项辨析: MVCC 不消灭死锁,不串行化读写,与复制延迟无关。
050 InnoDB 在 REPEATABLE READ 下如何避免幻读?
难度: 进阶
- A. 快照读用 MVCC 保证一致性,当前读与写用临键锁(记录锁加间隙锁)阻止插入
- B. 对所有表加全局写锁,禁止任何插入
- C. 仅靠可重复读隔离级别本身,无需任何锁
- D. 必须把隔离级别升到 SERIALIZABLE 才能读快照
查看答案与解析
正确答案A
正确原因: RR 下两类机制结合:MVCC 负责快照读,Next-Key Lock 负责当前读范围,阻止间隙内插入。
关键边界: 隔离级别并不能消除所有并发写异常,事务间写冲突仍要加锁等待。
错误选项辨析: 全局写锁过度且不必要,RR 本身包含锁机制,普通快照读不需要 SERIALIZABLE。
051 READ COMMITTED 与 REPEATABLE READ 在 InnoDB 中的核心区别是?
难度: 进阶
- A. RC 完全不加锁,RR 加全表锁
- B. RC 每条语句建立新快照,RR 在事务首次读后固定快照
- C. RC 不允许执行 UPDATE,只能 SELECT
- D. 两者实现完全一致,只是名字不同
查看答案与解析
正确答案B
正确原因: RC 下同一事务的每条语句都有新快照,RR 则从首次读开始固定整个事务的视图。
关键边界: 因此 RC 可能读到其他事务新提交的结果,RR 保持一致视图且间隙锁更积极。
错误选项辨析: RC 也会为写加锁,RC 支持全部 DML,两者实现差异明显。
052 一致性读(Consistent Nonlocking Read)适用于哪种语句?
难度: 进阶
- A. SELECT … FOR UPDATE
- B. 普通 SELECT,利用多版本返回符合隔离级别的快照,不加锁
- C. INSERT … SELECT 中的写入表
- D. UPDATE 语句定位待更新行
查看答案与解析
正确答案B
正确原因: 一致性读只服务不加锁的普通查询,通过多版本返回可见快照。
关键边界: 锁定读与写语句属于当前读,读取最新已提交数据并加锁。
错误选项辨析: FOR UPDATE、INSERT 写入表、UPDATE 定位都是当前读场景。
053 事务执行 COMMIT 与 ROLLBACK 的区别是?
难度: 基础
- A. COMMIT 只保存一半修改,ROLLBACK 保存另一半
- B. 两者都会清空 undo log 且无法回滚
- C. COMMIT 持久化全部修改;ROLLBACK 撤销事务内全部修改
- D. ROLLBACK 后数据仍在磁盘,需重启生效
查看答案与解析
正确答案C
正确原因: COMMIT 让修改生效并由 redo log 保证崩溃后可恢复,ROLLBACK 靠 undo log 恢复旧版本。
关键边界: 已提交事务无法回滚,回滚只作用于未提交事务。
错误选项辨析: COMMIT 是整体生效,ROLLBACK 立即撤销,undo log 在回滚后按需清理。
054 长事务(长时间未提交)的主要危害是?
难度: 进阶
- A. 长事务会自动提升隔离级别
- B. 长事务只会让主从复制变快
- C. 持有旧 ReadView 与锁,导致 undo 无法清理、空间膨胀并阻塞并发
- D. 长事务不消耗任何资源,可随意开启
查看答案与解析
正确答案C
正确原因: 长事务使旧版本持续被引用,purge 无法回收 undo,同时长时间持锁放大阻塞。
关键边界: 连接池不会自动结束错误路径中的事务,需要应用保证异常回滚。
错误选项辨析: 长事务不改变隔离级别,会拖慢复制并持续占用资源。
055 WAL(Write-Ahead Logging)的核心原则是?
难度: 基础
- A. 先改数据页再写日志,速度更快
- B. 只写日志不落盘,重启后数据丢失
- C. 日志只记录 SELECT,不记录写操作
- D. 先写 redo log,再落数据页,崩溃后可重放恢复
查看答案与解析
正确答案D
正确原因: 先记日志再落页,即使脏页未刷盘,崩溃后也能用日志重放恢复。
关键边界: group commit 批量刷日志可提升写入吞吐。
错误选项辨析: 反序写日志无法保证恢复,WAL 只记录写变更,不记录查询。
056 redo log 的作用是?
难度: 基础
- A. 记录逻辑 SQL 语句用于复制
- B. 保存行的旧版本供回滚
- C. 缓存查询结果提升读性能
- D. 记录物理页的修改,用于崩溃恢复时重放,保证已提交事务不丢失
查看答案与解析
正确答案D
正确原因: redo log 记录页面级修改,崩溃恢复时重放未刷盘的已提交事务。
关键边界: redo 是循环写,binlog 是追加写,两者职责不同。
错误选项辨析: 复制与逻辑恢复靠 binlog,回滚靠 undo log,读性能靠缓冲池与索引。
057 undo log 在事务回滚时的作用是?
难度: 基础
- A. 用旧版本覆盖已修改的数据,把行恢复到事务开始前
- B. 删除整个表空间文件
- C. 重放 redo 日志重新执行事务
- D. 把事务内 SQL 发送到从库执行
查看答案与解析
正确答案A
正确原因: 回滚时根据 undo 记录的逆操作恢复旧版本,撤销本次事务的修改。
关键边界: redo 是前滚恢复,undo 是回滚,方向相反且作用阶段不同。
错误选项辨析: 回滚不删表空间,不重放 redo,也不涉及从库。
058 MySQL 中 redo log 与 binlog 的“两阶段提交”解决什么问题?
难度: 进阶
- A. 让两个数据库事务同时提交
- B. 保证事务提交时两份日志一致,崩溃恢复后不会出现主从不一致
- C. 让 SELECT 与 UPDATE 同时执行
- D. 只影响 MyISAM,不影响 InnoDB
查看答案与解析
正确答案B
正确原因: 崩溃发生在 prepare 与 commit 之间时,通过 xid 对齐 binlog 与 redo,决定事务提交或回滚。
关键边界: 该机制服务于 InnoDB 与 Server 层日志的一致性,是复制正确性的基础。
错误选项辨析: 它不涉及多库事务协调,不并行执行语句,且主要针对 InnoDB。
059 高并发扣减库存时,比较稳妥的 SQL 写法是?
难度: 实战
- A. 先 SELECT 库存,再在应用层判断后 UPDATE
- B. UPDATE 不带条件,直接覆盖为固定值
- C. UPDATE stock SET quantity = quantity - ? WHERE product_id = ? AND quantity >= ?
- D. 先 DELETE 再 INSERT 整行记录
查看答案与解析
正确答案C
正确原因: 带剩余量条件的 UPDATE 是原子操作,受影响行数为 0 即可判定库存不足。
关键边界: 行锁竞争仍需控制事务长度并处理死锁重试。
错误选项辨析: 先查后改存在超卖竞态,无条件覆盖与删除重插会破坏数据。
060 业务代码中把 HTTP 调用放进数据库事务里,主要问题是什么?
难度: 实战
- A. 事务内网络调用会自动获得分布式事务保证
- B. 事务会因此自动变短,性能更优
- C. 数据库会拦截外部调用并代为重试
- D. 长事务持锁与快照,放大阻塞与回滚风险,外部调用失败也不受数据库回滚保护
查看答案与解析
正确答案D
正确原因: 外部副作用不随数据库回滚撤销,长事务还会长期持有锁与快照。
关键边界: 应通过本地消息表、Outbox 或补偿机制协调外部副作用。
错误选项辨析: 网络调用不会获得事务保证,事务不会变短,数据库不代理外部调用。