事务隔离和锁有什么关系?

事务隔离和锁是数据库并发控制的两个核心机制,二者紧密关联但职责不同:
事务隔离定义了事务之间的可见性规则(即“看到什么数据”),而是实现这些规则的技术手段(即“如何保证数据安全”)。


1. 事务隔离的四个级别

事务隔离级别由SQL标准(ANSI/ISO)定义,从低到高分为:

  1. 读未提交(Read Uncommitted):事务可能读到其他事务未提交的数据(脏读)。
  2. 读已提交(Read Committed):事务只能读到其他事务已提交的数据(解决脏读)。
  3. 可重复读(Repeatable Read):事务内多次读取同一数据的结果一致(解决不可重复读)。
  4. 串行化(Serializable):完全隔离,事务如同串行执行(解决幻读)。

不同数据库的默认隔离级别不同:

  • MySQL InnoDB默认 可重复读(通过MVCC+锁实现)。
  • Oracle/PostgreSQL默认 读已提交

2. 锁如何支撑事务隔离

锁是实现隔离级别的底层工具,不同隔离级别对锁的依赖程度不同:

隔离级别 锁的用途 典型问题
读未提交 几乎不加锁(仅写操作加排他锁,读不阻塞) 脏读、不可重复读、幻读
读已提交 写操作加排他锁(X锁),读操作不加锁(通过MVCC或短持有S锁) 不可重复读、幻读
可重复读 写操作加X锁,读操作利用MVCC或多版本快照(或长持有S锁) 幻读(部分数据库如MySQL通过间隙锁解决)
串行化 所有读操作加共享锁(S锁),写操作加X锁,可能使用范围锁(如间隙锁) 无并发问题,但性能最低

3. 关键交互场景

(1)读操作与锁
  • 脏读避免
    在“读已提交”及以上级别,写事务持有X锁时,其他事务无法读取未提交数据(X锁阻塞读请求)。
  • 不可重复读避免
    • 锁方案:事务A读取数据时加S锁,事务B的X锁会被阻塞(直到A提交)。
    • MVCC方案(无锁):通过多版本快照保证事务内读到同一版本数据(如MySQL的ReadView)。
(2)写操作与锁
  • 更新冲突
    两个事务同时更新同一行时,后请求X锁的事务会被阻塞(依赖排他锁)。
  • 幻读解决
    • 锁方案:串行化级别下,通过间隙锁(Gap Lock)或Next-Key Lock锁定范围,禁止其他事务插入符合条件的数据。
    • MVCC方案:可重复读级别下,通过快照避免“看到”新插入的数据(但可能仍存在写入冲突)。

4. 锁的类型与隔离级别

不同隔离级别对锁的需求不同:

  • 共享锁(S锁)
    • 高隔离级别(如串行化)中用于读操作,阻塞其他事务的X锁。
    • 低隔离级别(如读已提交)可能不加S锁(通过MVCC实现)。
  • 排他锁(X锁)
    • 所有隔离级别的写操作必须加X锁,确保数据修改的独占性。
  • 意向锁(IS/IX)
    • 在多粒度锁(如表+行)中协调锁冲突,与隔离级别无关。
  • 间隙锁(Gap Lock)
    • 仅在可重复读/串行化级别使用,解决幻读问题。

5. 示例对比

场景:事务A查询,事务B更新同一行
隔离级别 事务A操作 事务B操作 结果
读未提交 SELECT * FROM t UPDATE t SET ... A可能读到B未提交的脏数据
读已提交 SELECT * FROM t UPDATE t SET ... A只能读到B提交后的数据
可重复读 SELECT * FROM t UPDATE t SET ... A始终读到事务开始时的快照数据
串行化 SELECT * FROM t UPDATE t SET ... B的UPDATE可能被阻塞(若A持有S锁)

6. 总结

  • 锁是工具,隔离是目标
    锁通过阻塞或冲突检测保证数据一致性,隔离级别则定义了事务间的可见性边界。
  • 隔离级别越高,锁的代价越大
    串行化需要严格的锁机制(如范围锁),而读已提交可能仅依赖短持有锁或MVCC。
  • 现代数据库的优化
    多数数据库(如MySQL、PostgreSQL)结合 锁(悲观并发控制)MVCC(乐观并发控制) 实现高性能隔离。

理解二者的关系,有助于根据业务需求权衡 一致性并发性能

你可能感兴趣的:(数据库,数据库)