事务、隔离级别、锁与死锁
081 事务的原子性(Atomicity)保证的是?
难度: 基础
- A. 事务内操作要么全部生效,要么全部回滚,不允许部分成功
- B. 并发事务完全互不影响
- C. 事务执行时间恒定
- D. 事务外副作用自动回滚
查看答案与解析
正确答案A
正确原因: 原子性通过 undo 与回滚机制保证整体提交或整体撤销。
关键边界: 外部副作用(消息、接口)不随数据库回滚。
错误选项辨析: 互不影响是隔离性,执行时间不保证,外部副作用不自动回滚。
082 PostgreSQL 的默认隔离级别是?
难度: 基础
- A. READ COMMITTED
- B. READ UNCOMMITTED
- C. REPEATABLE READ
- D. SERIALIZABLE
查看答案与解析
正确答案A
正确原因: PG 默认 READ COMMITTED,每条语句获取独立快照,与 MySQL 默认不同。
关键边界: 可逐事务或全局调整隔离级别。
错误选项辨析: READ UNCOMMITTED 在 PG 中行为等同 READ COMMITTED,RR 与 SERIALIZABLE 都非默认。
083 脏读(Dirty Read)指的是?
难度: 基础
- A. 读到已提交但被更新的数据
- B. 读到其他事务未提交、可能被回滚的数据
- C. 两次读取结果不同
- D. 读到主从延迟的旧数据
查看答案与解析
正确答案B
正确原因: 脏读读取未提交数据,该数据可能回滚消失。
关键边界: PG 的 READ COMMITTED 及更高级别都不出现脏读。
错误选项辨析: 已提交更新是快照差异,两次不同是重复读问题,复制延迟不是脏读。
084 可重复读(REPEATABLE READ)下,PostgreSQL 的表现是?
难度: 进阶
- A. 每条语句都建立新快照
- B. 整个事务使用同一快照,普通查询看不到其他事务的新提交,但更新冲突会报错
- C. 不允许任何写操作
- D. 与 READ COMMITTED 完全相同
查看答案与解析
正确答案B
正确原因: PG 的 RR 使用事务级快照,保证一致性读,写冲突时可能返回序列化错误。
关键边界: 应用需把该错误视为可重试。
错误选项辨析: 语句级快照是 READ COMMITTED,RR 允许写,两者差异明显。
085 SERIALIZABLE 隔离级别在 PG 中的实现是?
难度: 进阶
- A. 给所有读取加排他锁
- B. 所有事务排队串行执行
- C. 基于可串行化快照隔离(SSI)检测危险读写结构并中止部分事务
- D. 只是名字不同,行为同 RR
查看答案与解析
正确答案C
正确原因: SSI 监控读写依赖,检测到可能破坏可串行化时中止事务。
关键边界: 应用必须重试 SQLSTATE 40001。
错误选项辨析: 不是加锁串行,不是排他锁,行为确实比 RR 严格。
086 PG 的 MVCC 中,事务快照(ReadView)的作用是?
难度: 进阶
- A. 记录所有历史 SQL 文本
- B. 决定表空间大小
- C. 记录活跃事务集合,判断版本链中哪些版本可见
- D. 控制磁盘刷盘时机
查看答案与解析
正确答案C
正确原因: 快照包含事务开始时的活跃事务 id,据此确定行的可见版本。
关键边界: READ COMMITTED 每条语句建快照,RR 整个事务一个快照。
错误选项辨析: 快照与 SQL 审计、表空间、刷盘无关。
087 SELECT … FOR UPDATE 的行为是?
难度: 基础
- A. 不加任何锁
- B. 读取历史版本快照
- C. 锁定整张表禁止查询
- D. 锁定选中的行直到事务结束,阻止其他事务修改
查看答案与解析
正确答案D
正确原因: FOR UPDATE 加行级排他锁,写冲突者等待,普通查询不受影响。
关键边界: 锁在事务提交或回滚时释放。
错误选项辨析: 它加锁而非快照读,锁行而非整表,普通 SELECT 不被阻塞。
088 乐观并发控制(乐观锁)的典型实现是?
难度: 进阶
- A. 先对整表加锁再更新
- B. 更新时不带任何条件
- C. 使用 FOR UPDATE 长时间持锁
- D. 更新时带版本号或旧值条件,受影响行数为 0 表示冲突
查看答案与解析
正确答案D
正确原因: 条件更新把状态校验放进 WHERE,行数为 0 时判定冲突。
关键边界: 应用必须处理行数为 0 的情况,重试或返回错误。
错误选项辨析: 表锁与 FOR UPDATE 是悲观思路,无条件更新无法检测冲突。
089 死锁发生的必要条件是?
难度: 基础
- A. 多个事务以不同顺序持有资源并互相等待,形成循环
- B. 只有一个事务执行写操作
- C. 所有事务都只读
- D. 磁盘空间不足
查看答案与解析
正确答案A
正确原因: 互斥、持有并等待、不可剥夺与循环等待同时成立才会死锁。
关键边界: PG 检测到死锁会中止其中一个事务。
错误选项辨析: 单写者或全只读不会形成循环等待,磁盘与死锁无关。
090 SAVEPOINT 的作用是?
难度: 进阶
- A. 在事务内设置回滚点,可只撤销该点之后的修改
- B. 提交事务的前半部分
- C. 开启一个全新事务
- D. 给事务加唯一编号
查看答案与解析
正确答案A
正确原因: SAVEPOINT 支持事务内局部回滚,适合错误分支处理。
关键边界: 回滚到保存点不结束事务,之前获取的资源不一定释放。
错误选项辨析: 它不是提交,不开启新事务,编号是次要功能。
091 advisory lock(咨询锁)的特点是?
难度: 进阶
- A. 自动阻止所有相关业务写入
- B. 由应用约定语义的锁,数据库不绑定业务行完整性
- C. 事务回滚时自动释放会话锁
- D. 只能由超级用户使用
查看答案与解析
正确答案B
正确原因: 咨询锁按应用协议使用,键值由应用设计,与会话或事务绑定。
关键边界: 会话级咨询锁需显式释放,事务级随事务结束。
错误选项辨析: 它不自动理解业务,会话锁不随事务释放,普通用户也可用。
092 关于 PostgreSQL 的锁升级,正确的是?
难度: 进阶
- A. 行锁过多会自动升级为表锁
- B. PG 不自动升级行锁,锁数量多时通过锁表或优化查询控制
- C. 表锁一定比行锁慢
- D. PG 没有表锁
查看答案与解析
正确答案B
正确原因: PG 采用行锁而非锁升级策略,通过锁表、限制扫描范围或拆分事务缓解。
关键边界: LOCK TABLE 可显式加表锁,锁表会阻塞相关 DML。
错误选项辨析: 无自动升级,表锁粒度大但开销小,PG 支持表锁。
093 事务开启后空闲(idle in transaction)的主要危害是?
难度: 实战
- A. 自动释放所有资源
- B. 提升查询性能
- C. 长期持有快照与锁,阻碍 VACUUM 回收死元组并阻塞并发
- D. 只影响连接池大小
查看答案与解析
正确答案C
正确原因: 空闲事务仍持有快照和锁,事务更早开启的死元组无法清理。
关键边界: 连接池不会自动结束错误路径中的事务,需应用保证提交或回滚。
错误选项辨析: 资源不会自动释放,性能下降而非提升,影响远超连接数。
094 外键检查对并发写入的影响是?
难度: 进阶
- A. 外键完全不参与加锁
- B. 只影响 SELECT
- C. 在父表上加锁保护引用完整性,可能形成锁等待
- D. 外键会禁用事务
查看答案与解析
正确答案C
正确原因: 插入子行要确认父行存在,相关行会被加锁,删除父行会与子表操作竞争。
关键边界: 高并发 DML 时外键是常见锁等待来源。
错误选项辨析: 外键参与锁机制,影响写入路径,不影响事务能力。
095 查看当前锁等待情况,应查询?
难度: 基础
- A. pg_stat_statements
- B. information_schema.tables
- C. pg_roles
- D. pg_locks 视图与 pg_stat_activity 结合分析
查看答案与解析
正确答案D
正确原因: pg_locks 展示锁与等待关系,pg_stat_activity 提供会话与 SQL 上下文。
关键边界: 两者联查可定位阻塞链。
错误选项辨析: 另外三个对象分别服务语句统计、表元数据与角色。
096 REPEATABLE READ 下两个事务更新同一行,后提交者会遇到?
难度: 进阶
- A. 静默覆盖对方修改
- B. 自动合并两个更新
- C. 直接等待无限时间
- D. ERROR: could not serialize access due to concurrent update,需要重试
查看答案与解析
正确答案D
正确原因: PG 的 RR 在更新冲突时返回序列化错误,而非覆盖。
关键边界: 应用应捕获该错误并重试整个事务。
错误选项辨析: 不会静默覆盖或合并,也不会无限等待。
097 高并发扣减库存,更稳妥的 SQL 写法是?
难度: 实战
- A. UPDATE stock SET quantity = quantity - ? WHERE id = ? AND quantity >= ?
- B. 先 SELECT 再在应用层判断后 UPDATE
- C. 无条件 UPDATE 覆盖固定值
- D. 先 DELETE 再 INSERT
查看答案与解析
正确答案A
正确原因: 条件更新原子完成校验与扣减,受影响行数反映是否成功。
关键边界: 热点行仍会串行,需配合队列或限流。
错误选项辨析: 先查后改存在竞态,无条件覆盖与删除重插破坏数据。
098 排查死锁时首先应该?
难度: 实战
- A. 重启数据库清空现场
- B. 查看数据库日志或 pg_locks,分析涉及的语句与锁顺序
- C. 删除全部索引
- D. 把隔离级别降到最低
查看答案与解析
正确答案B
正确原因: 死锁日志记录参与语句与锁顺序,据此统一访问顺序或拆分事务。
关键边界: 改隔离级别不能根治写写冲突。
错误选项辨析: 重启丢现场,删索引与降隔离级别都不是定位手段。
099 BEGIN READ ONLY 事务的特点是?
难度: 进阶
- A. 事务可以写入但不可回滚
- B. 只读事务不需要快照
- C. 事务只允许查询,不允许写入,某些场景可减少快照开销
- D. 只读事务不能使用索引
查看答案与解析
正确答案C
正确原因: 只读事务明确禁止 DML,适合纯查询场景,并允许部分优化。
关键边界: 尝试写入会报错,快照规则与其他事务一致。
错误选项辨析: 只读仍用快照,支持索引,不允许写入。
100 序列(sequence)与事务并发的关系是?
难度: 基础
- A. 并发事务可能拿到相同序列值
- B. 序列值受事务回滚影响
- C. 序列只能在单会话使用
- D. nextval 原子分配,不回滚复用,并发事务拿到不同值
查看答案与解析
正确答案D
正确原因: 序列分配与事务隔离,值唯一递增,回滚不回收。
关键边界: 因此序列值可能有空洞,但不会重复。
错误选项辨析: 并发不会拿到相同值,回滚不回收,序列可跨会话共享。