找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

393

积分

1

好友

43

主题
发表于 昨天 04:41 | 查看: 16| 回复: 0

MySQL的锁机制是保障数据一致性和事务隔离性的核心,其设计较为复杂,涉及不同存储引擎与业务场景。为了帮助开发者建立系统的认知,我们通常可以从以下四个维度来系统性地理解MySQL的锁。

一、按锁的“粒度”分类(最常见)

1. 表级锁(Table Lock)

此锁会锁定整张表,其特点是锁粒度最大、加锁开销最小,但并发度最低,容易发生锁冲突。

  • 适用场景:主要见于MyISAM引擎,或在执行DDL(如ALTER TABLE)操作时。
  • 主要特点
    • 加锁与释放锁的速度很快。
    • 并发能力弱,写操作会阻塞其他所有的读写操作,读操作会阻塞其他写操作。
2. 行级锁(Row Lock)✔ InnoDB使用最广泛

行锁仅锁定需要访问的数据行,粒度小,能极大提升数据库的并发处理能力。

  • 主要类型
    • 行共享锁(S Lock)
    • 行排他锁(X Lock)
  • 主要特点
    • 并发性能优异。
    • 加锁、释放锁的开销较大。
    • 在高并发场景下,可能产生死锁问题。
3. 页级锁(Page Lock)

锁的粒度介于表锁和行锁之间,会锁定一页数据(通常为16KB)。

  • 常见引擎:曾用于BDB存储引擎,现已很少使用。

二、按锁的“读写”性质分类

1. 共享锁(Shared Lock,S 锁)

又称为“读锁”。一个事务获取某行的共享锁后,自身可以读该行,其他事务也可以读该行,但任何事务都不能写该行。

  • 加锁SQL示例
    SELECT * FROM t WHERE id = 1 LOCK IN SHARE MODE;
2. 排他锁(Exclusive Lock,X 锁)

又称为“写锁”。一个事务获取某行的排他锁后,自身可以读写该行,其他事务既不能读也不能写该行。

  • 加锁SQL示例
    SELECT * FROM t WHERE id = 1 FOR UPDATE;

    UPDATEDELETEINSERT语句通常会隐式地对涉及的行加排他锁。

三、按“意向”分类(InnoDB 特有)

意向锁是一种表级锁,用于表明某个事务“有意向”在表中的某些行上加特定类型的锁,从而避免在加表锁时需要逐行检查是否有冲突的行锁。

1. 意向共享锁(IS)

表示事务计划对表中的某些行加共享锁(S锁)。

2. 意向排他锁(IX)

表示事务计划对表中的某些行加排他锁(X锁)。

工作机制:当你要给某一行加X锁时,必须先成功给其所在的表加上IX锁。这种机制极大地提升了InnoDB在表级操作时的锁冲突检测效率。

四、InnoDB 特有的行级锁(核心考点)

1. 记录锁(Record Lock)

锁定索引中的一条具体记录。

  • 示例SELECT * FROM user WHERE id = 10 FOR UPDATE; 会锁住id=10这条索引记录。
2. 间隙锁(Gap Lock)

锁定索引记录之间的“间隙”(一个开区间),防止其他事务在间隙中插入新数据,从而解决“幻读”问题。

  • 示例:锁住id在(10, 20)之间的这个范围,即使id=15的记录不存在,也无法被插入。
3. 临键锁(Next-Key Lock)✔ 默认模式

InnoDB在可重复读(RR)隔离级别下的默认行锁算法。它是记录锁(Record Lock)与间隙锁(Gap Lock)的结合,锁定一个左开右闭的区间。

  • 示例:锁定区间(10, 20],既锁定了id=20的记录,也锁定了(10, 20)这个间隙。
4. 插入意向锁(Insert Intention Lock)

一种特殊的间隙锁。当多个事务试图在同一个间隙中插入不同位置的数据时,它们会互相兼容地加上插入意向锁,不会彼此阻塞,以此提升插入并发效率。

5. 自增锁(AUTO-INC Lock)

一种特殊的表级锁,用于在表存在AUTO_INCREMENT列时,保障自增主键值的唯一性和连续性。

  • 模式:通过innodb_autoinc_lock_mode参数可配置为传统表锁模式或更轻量的交错模式。

五、按“是否阻塞”分类

1. 乐观锁(Optimistic Lock)

并非数据库内置的锁,而是一种并发控制思想。它假设多事务并发冲突的概率较低,因此在更新数据时才进行冲突检测(通常基于版本号或时间戳)。

  • 适用场景:读多写少,冲突不频繁的业务。
  • 实现示例
    UPDATE t SET num=num+1, version=version+1 WHERE id=1 AND version=100;

    这种思想在后端开发中,常通过应用层逻辑配合数据库实现。

2. 悲观锁(Pessimistic Lock)

即数据库提供的排他锁(X锁)。它假设并发冲突总会发生,因此在操作数据前就先加锁,确保独占。

  • 适用场景:写操作频繁,冲突概率高的业务。
  • 典型实现:使用SELECT ... FOR UPDATE

六、按“DDL/DML”分类

1. 元数据锁(MDL Lock)

MySQL 5.5+引入,用于保护表结构(元数据)的一致性,避免在查询或修改表数据时,表结构被更改。

  • 读锁(共享):在执行DML(SELECT, INSERT, UPDATE, DELETE)时自动加MDL读锁。
  • 写锁(排他):在执行DDL(如ALTER TABLE)时自动加MDL写锁。
  • 常见问题:一个未提交的长事务(持有MDL读锁)会阻塞所有DDL操作;反过来,一个DDL操作(持有MDL写锁)会阻塞后续所有DML操作。这是运维中需要警惕的阻塞场景。
2. 备份锁(Backup Lock)

MySQL 8.0引入,用于在在线物理备份期间锁定,以阻止可能影响备份一致性的DDL操作,同时最小化对普通DML操作的影响。

七、加锁总结表

锁类型 发生位置 核心特点 典型场景/示例
表锁 粒度大,加锁快,并发低 MyISAM引擎,DDL操作
行锁 索引记录 粒度小,并发高,开销大 InnoDB引擎的DML操作
共享锁(S) 读锁,允许多个事务并发读 SELECT ... LOCK IN SHARE MODE
排他锁(X) 写锁,独占访问 SELECT ... FOR UPDATE
意向锁(IS/IX) 辅助锁,提升锁冲突检测效率 InnoDB自动管理
记录锁 精确锁定单条索引记录 主键/唯一索引等值查询
间隙锁 索引间隙 防止幻读,锁定范围 范围查询,非唯一索引等值查询
临键锁 行+间隙 默认锁类型,解决幻读 RR隔离级别下的索引查询
自增锁 保护自增列唯一性 插入带AUTO_INCREMENT列的表
MDL锁 表结构 控制DDL与DML的并发 执行ALTER TABLE

总结

MySQL的锁体系以表级锁、行级锁和页锁为基本粒度。现代InnoDB引擎的核心是行级锁,其下又衍生出共享锁、排他锁、意向锁、记录锁、间隙锁、临键锁、插入意向锁和自增锁等丰富类型。此外,元数据锁(MDL)是保护表结构的关键。不同的锁在性能与并发安全之间进行权衡,开发者需根据实际业务场景和隔离级别,深入理解其原理,才能编写出高效、安全的数据库应用。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-3 14:19 , Processed in 0.058438 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表