MySQL 数据库系统在 server 层和存储引擎层都广泛应用了各种锁机制,以确保并发操作下的数据一致性及完整性。本文将详细介绍MySQL中两种关键类型的server层锁以及InnoDB存储引擎的表级和行级锁。
1. Server层锁
1.1 Metadata Lock (MDL)
MDL,即元数据锁,是在server层针对数据库元数据资源采用的一种锁定机制。元数据包括但不限于表结构、索引定义、视图定义等非用户数据部分。MDL 主要服务于以下两个目的:
- 事务隔离问题:防止在事务执行过程中其他会话修改相关的表结构,造成数据一致性问题。
- 数据复制问题:在复制环境中,确保所有副本的元数据变更在同步期间的一致性。
1.2 Table Locks
MySQL server层还支持Table Lock,即表锁。表锁是对整个数据表进行锁定,锁定期间,其他会话无法对该表进行写入或可能的并发读取,具体锁定粒度较粗,适合在简单并发环境下提高处理速度。
2. InnoDB 存储引擎表级锁
InnoDB 存储引擎提供了多种表级锁,主要应用在DDL操作或者特定条件下:
- IS (意向共享锁):表示事务打算在表的某些记录上获取S锁。
- IX (意向排他锁):表示事务打算在表的某些记录上获取X锁。
- S (共享锁):允许事务读取一行数据,多个事务可以同时持有同一记录的S锁。
- X (排他锁):允许事务更新或删除一行数据,只有单个事务能持有记录的X锁。
- AUTO-INC锁:针对具有
AUTO_INCREMENT
属性的列,此锁是语句级别的,确保在同一事务中自增序列值的单调递增且互斥分配。
3. InnoDB 存储引擎行级锁
InnoDB 引擎进一步细化锁定粒度至行级,提高了并发性能:
- RecordLock:记录锁直接锁定具体的行记录,防止其他事务对此记录进行修改。
- GapLock:间隙锁用于解决“幻读”问题,它锁定的是记录之间的间隙,防止在已锁定间隙中插入新记录。
- Next-KeyLock:它是RecordLock和GapLock的结合,不仅锁定记录本身,还锁定记录前后的间隙,防止幻读现象。
- InsertIntentionLock:插入意向锁是在事务尝试插入间隙时获取的,用于协调多个事务在同一间隙内插入记录的行为,减少不必要的等待。
4. 行锁与表锁的选择
在实际应用中,行锁适用于高并发环境下的读写操作,特别是对于涉及大量行记录且频繁更新的情况,可以大大提升并发性能。而全表扫描操作由于无法确定锁定的具体行,通常倾向于使用表锁。
5. 幻读理解
幻读是指在一个事务中按照相同的条件执行两次查询,第一次查询没有返回某些特定记录,但是在第二次查询时却发现了这些原本“不存在”的记录。这是因为在两次查询之间,其他事务插入了满足条件的新记录,并提交了事务。间隙锁和Next-KeyLock正是为了防止此类幻读现象的发生。