MySQL通过锁机制保证并发下的数据一致性,按粒度分为行级锁、表级锁和页级锁,按模式分为共享锁与排他锁,InnoDB特有意向锁、间隙锁、临键锁和插入意向锁;MyISAM仅支持表级锁,InnoDB默认行级锁并结合MVCC提升并发性能;SELECT...LOCK IN SHARE MODE加S锁,FOR UPDATE及DML语句自动加X锁;不同隔离级别下锁策略不同,RR级别通过临键锁防止幻读,Serializable则所有读操作均加S锁;锁等待受超时控制,InnoDB可自动检测并回滚死锁事务,建议按序访问资源、减小事务范围以避免死锁。

MySQL的锁机制是保证数据库在并发操作下数据一致性和完整性的核心手段。不同场景下,MySQL会使用不同类型的锁来控制多个事务对同一数据的访问,避免出现脏读、不可重复读、幻读等问题。
1. 锁的分类
按粒度划分:
- 行级锁(Row-level Lock):锁定某一行数据,适用于InnoDB存储引擎。并发性能高,但开销稍大。
- 表级锁(Table-level Lock):锁定整张表,MyISAM和InnoDB都支持。开销小,但并发性能差,容易造成阻塞。
- 页级锁:介于行锁和表锁之间,锁定一页数据(如B+树的一个节点),使用较少。
按模式划分:
- 共享锁(S锁 / 读锁):多个事务可以同时持有S锁读同一数据,但不能修改。其他事务可以加S锁,不能加X锁。
- 排他锁(X锁 / 写锁):事务写数据时加X锁,其他事务无法加任何锁,直到释放。
特殊锁类型(InnoDB特有):
- 意向锁(Intention Lock):表明事务打算在某行上加S锁或X锁。分为意向共享锁(IS)和意向排他锁(IX)。用于快速判断是否可以加表锁。
- 间隙锁(Gap Lock):锁定索引记录之间的“间隙”,防止其他事务插入新记录,解决幻读问题。
- 临键锁(Next-Key Lock):行锁 + 间隙锁的组合,锁定记录及其前面的间隙,是InnoDB默认的行锁机制。
- 插入意向锁(Insert Intention Lock):多个事务在不同间隙插入数据时使用,提高并发插入效率。
2. 不同存储引擎的锁表现
MyISAM:只支持表级锁,读操作自动加S锁,写操作加X锁。读写互斥,写操作期间其他操作全部阻塞。
InnoDB:默认行级锁,支持MVCC(多版本并发控制),读不加锁(快照读),写才加锁。只有当前读(如SELECT ... FOR UPDATE)才会显式加锁。
3. 如何触发锁
常见加锁语句:
-
SELECT ... LOCK IN SHARE MODE;—— 加共享锁(S锁) -
SELECT ... FOR UPDATE;—— 加排他锁(X锁) -
UPDATE、DELETE、INSERT—— 自动加X锁
注意:普通SELECT在可重复读隔离级别下使用MVCC,不加锁。
4. 锁与事务隔离级别的关系
- 读未提交(Read Uncommitted):几乎不加锁,允许脏读。
- 读已提交(Read Committed):写加X锁,读不加锁,但每次读取最新已提交版本。
- 可重复读(Repeatable Read):InnoDB通过临键锁 + MVCC防止幻读。
- 串行化(Serializable):所有读操作自动加S锁,写加X锁,完全串行执行。
5. 锁等待与死锁
当一个事务等待另一个事务释放锁时,发生锁等待。MySQL会设置超时时间(innodb_lock_wait_timeout),超过则报错。
死锁是指两个或多个事务相互等待对方释放锁。InnoDB能自动检测死锁并回滚其中一个事务。
避免死锁的方法:
- 按相同顺序访问表和行
- 减少事务大小,尽快提交
- 避免长时间持有锁
基本上就这些。理解MySQL锁机制的关键是结合存储引擎、隔离级别和具体SQL语句来看,尤其是InnoDB的行锁实现较为复杂但高效。










