MySQL的那些鲜为人知的锁(1)

MySQL的那些鲜为人知的锁(1)
最新回答
╭⌒浅痛

2026-04-08 13:56:11

MySQL中鲜为人知的锁包括全局锁、意向锁、自增锁,以下是对这些锁的详细介绍:

全局锁
  • 定义与命令:全局锁是对整个数据库实例进行加锁,加锁后整个数据库处于只读状态。加锁命令为flush tables with read lock (FTWRL),释放锁的命令为unlock tables。
  • 阻塞语句:

    DML语句中的insert、update、delete操作。

    所有DDL语句。

    更新类事务的提交语句。

  • 使用场景:主要用于全库逻辑备份,确保备份期间数据的一致性。
  • 缺陷:

    对主库使用全局锁备份会导致业务停滞。

    对从库使用全局锁备份会导致主从延迟。

  • 优化方案:在InnoDB存储引擎的可重复读隔离级别下,使用mysqldump工具并设置--single-transaction参数,通过MVCC机制实现一致性备份,同时允许数据更新。
意向锁
  • 定义:意向锁是表级锁,用于表示事务打算在表中的行上获取什么类型的锁(共享锁或独占锁)。
  • 目的:提高加表锁的效率。在加表锁前,通过检查意向锁避免遍历表中所有行。
  • 工作原理:

    事务A在行上加独占锁时,数据库会自动给事务A加上该表的意向独占锁。

    事务B尝试加表锁时,通过检查意向锁判断表中是否有行被锁定。

  • 兼容性:意向锁之间相互兼容,例如意向共享锁和意向独占锁可以同时存在。
  • 示例:

    事务A执行update product set quantity = quantity -1 where id = 10,在id=10的行上加独占锁,并自动加表的意向独占锁。

    事务B执行update product set quantity = quantity +10,尝试加表锁时,通过检查意向锁判断表中是否有行被锁定。

自增锁
  • 定义:自增锁是一种特殊的表锁,用于实现自增主键的约束。当一个事务要插入新数据并获取下一个自增值时,会先获取自增锁。
  • 工作原理:

    事务获取自增锁后,执行插入操作并确保自增值的唯一性和连续性(是否连续取决于参数设置)。

    自增锁在SQL语句执行完成后立即释放,而非事务完成后释放,以提高性能。

  • 自增计数器:InnoDB为每个含自增列的表维护一个内存中的自增长计数器,插入时通过select max(auto_inc_col) from t for update获取当前值并加1。
  • 性能优化:

    从MySQL 5.1.22开始,使用轻量级的内存mutex锁替代传统表锁,通过估算插入数量减少锁竞争。

    提供innodb_autoinc_lock_mode参数控制自增模式,支持三种模式:

    0(Traditional):所有插入语句获取表级自增锁,语句结束后释放,保证自增值连续。

    1(Consecutive):简单插入和混合插入使用mutex锁,批量插入使用表锁,平衡性能与连续性。

    2(Interleaved):所有插入语句不使用表锁,高并发下性能最佳,但自增值可能不连续。

  • 空洞问题:

    事务回滚会导致自增值丢失,产生空洞。

    批量插入(Bulk inserts)在模式0或1下自增值连续,模式2下可能因预分配过多ID产生空洞。

    混合插入(Mixed-mode inserts)在模式1或2下可能因分配未使用的ID产生空洞。

  • 示例:

    简单插入:insert into values (1, 'a')。

    批量插入:insert ... select。

    混合插入:INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d')。

总结:全局锁、意向锁和自增锁是MySQL中相对鲜为人知但重要的锁机制。全局锁用于全库备份,意向锁优化表锁加锁效率,自增锁确保自增主键的唯一性和连续性(受参数控制)。理解这些锁的工作原理和适用场景,有助于优化数据库性能和避免并发问题。