并发控制的核心目标

在多个事务同时访问数据库时,确保数据的一致性(Consistency)和事务的隔离性(Isolation)

  • 丢失更新(Lost Update):两个事务同时修改同一数据,后提交的覆盖了先提交的结果。
  • 脏读(Dirty Read):事务读取到其他未提交事务的中间数据。
  • 不可重复读(Non-repeatable Read):同一事务内多次读取同一数据结果不同。
  • 幻读(Phantom Read):同一事务内多次查询返回的行数不同(因其他事务插入/删除了数据)。

并发控制

通过锁协调事务对数据的访问,分为两类:

  • 共享锁(Shared Lock, S-Lock)
    • 事务读取数据时加锁,允许其他事务加共享锁,但禁止加排他锁。
    • 示例:SELECT * FROM table WHERE ... LOCK IN SHARE MODE;
  • 排他锁(Exclusive Lock, X-Lock)
    • 事务修改数据时加锁,禁止其他事务加任何锁。
    • 示例:SELECT * FROM table WHERE ... FOR UPDATE;

锁的粒度

  • 行级锁(Row-level Lock):锁定单行(如InnoDB)。
  • 表级锁(Table-level Lock):锁定整表(如MyISAM)。

两阶段锁协议(2PL, Two-Phase Locking)

  • 扩展阶段:事务可以不断加锁,但不能释放锁。
  • 收缩阶段:事务只能释放锁,不能再加锁。
  • 确保可串行化,但可能导致死锁。

时间戳排序(Timestamp Ordering)

基本思想:为每个事务分配唯一时间戳,按时间戳顺序处理冲突操作。
规则:

若事务A要读取数据,必须保证该数据的最新写入时间戳 ≤ 事务A的时间戳。
若事务A要写入数据,必须保证该数据的最后读取时间戳 ≤ 事务A的时间戳,且最后写入时间戳 ≤ 事务A的时间戳。

优点:避免死锁;缺点:可能因冲突导致事务回滚。

事务隔离级别

数据库通过不同的隔离级别平衡并发性能和数据一致性。常见的隔离级别(由低到高):

读未提交(Read Uncommitted)

允许脏读、不可重复读、幻读。

读已提交(Read Committed)

禁止脏读,但允许不可重复读和幻读(多数数据库的默认级别)。

可重复读(Repeatable Read)

禁止脏读和不可重复读,允许幻读(MySQL InnoDB默认级别,通过MVCC消除幻读)。

串行化(Serializable)

完全禁止并发问题,但性能最低。