MySQL锁
全局锁
一般在做全库备份的时候用到。会阻塞写操作,只允许读请求。因此一般选在业务低峰期去做全库备份。
|
|
表级锁
表锁
- 表共享读锁。多个线程能同时获取这个锁,获取锁的线程可以读这个表,但不能写这个表。MyISAM 处理读请求时,会获取该表的表共享读锁。而 InnoDB 默认是行锁,通过 MVCC 来处理读请求。
- 表独占写锁。只有一个线程能获取这个锁,它可以对表进行写操作。其它任何线程都不可以读这张表。
|
|
触发表锁:ALTER/DROP/TRUNCATE TABLE
意向锁
意向锁是表级锁,它的主要作用是避免全表扫描。(🌟号操作体现)
InnoDB 里面读某个 record,通过无锁的 MVCC 机制来实现,此时不会给表加意向锁。
意向锁和行级锁不冲突,意向锁之间也不冲突。
锁类型 | 表级 S 锁(共享锁) | 表级 X 锁(排他锁) | 表级 IS 锁(意向共享锁) | 表级 IX 锁(意向排他锁) |
---|---|---|---|---|
表级 S 锁(共享锁) | 兼容 | 冲突 | 兼容 | 兼容 |
表级 X 锁(排他锁) | 冲突 | 冲突 | 冲突 | 冲突 |
表级 IS 锁(意向共享锁) | 兼容 | 冲突 | 兼容 | 兼容 |
表级 IX 锁(意向排他锁) | 冲突 | 冲突 | 兼容 | 兼容 |
意向读锁IS
|
|
当我们通过这种操作去读某一行数据时,会给这一行加上行级读锁,这时候数据库也会给这个表加上表级意向读锁。
- 当有其它线程给某一行加写锁时,根据索引判断这行是否加了读锁,如果没加,写锁可以被加上;如果这行已经加了读锁,则不能加写锁。
- 当有其它线程给全表加写锁时,会发现表已经有意向读锁,因此不能完成写操作。🌟
- 当有其它线程给某一行/全表加读锁时,不冲突
意向写锁IX
|
|
这个操作给这个表加上意向写锁,并且给该行加上写锁。
- 当有其它线程给某一行加写锁时,根据索引判断这行是否已经有写锁,如果没有,写锁可以被加上;如果这行已经加了写锁,则不能再加写锁。
- 当有其它线程给全表加写锁时,会发现表已经有意向写锁,因此不能完成写操作。🌟
- 当有其它线程给某一行加读锁时,根据索引判断是不是同一行,如果是,则读锁不能加上;如果不是,可以加上
- 当有其它线程给全表加读锁时,可以完成。
行锁
行锁是一种精确到数据库表中某一行数据的锁.
行级锁 Record Lock
区分行级读锁/写锁
间隙锁(Gap Lock)
间隙锁锁定的是两个相邻索引记录之间的 “间隙”,这里的间隙包括左开右开、左闭右开、左开右闭三种形式。
间隙锁是 InnoDB 在**可重复读(Repeatable Read, RR)**隔离级别下特有的一种锁,用于锁定索引记录之间的“间隙”(即两个索引值之间的范围)。
它的核心作用是 防止其他事务在间隙中插入新数据,从而解决幻读问题。
可能会产生死锁问题。
Next - Key Lock
Next - Key Lock 是一种组合锁,它由行锁和间隙锁组成。它锁定的范围是左开右闭区间。
整合行锁与间隙锁:它既可以锁定精确的数据行(行锁的功能),又可以锁定数据行之间的间隙(间隙锁的功能),提供更全面的保护。
面试问题
- 在 MySQL 中,如果一条 UPDATE 语句没有带 WHERE 条件,InnoDB 引擎会对整个表加 IX 锁(意向排他锁),并对所有行加 X 锁(排他锁),确保事务的原子性和一致性。而 MyISAM 引擎会对整个表加 写锁(排他锁),阻塞其他所有读写操作。
- 如果 UPDATE 语句带了 WHERE 条件,InnoDB 引擎会对符合条件的行加 X 锁(排他锁),并在可重复读隔离级别下加 间隙锁 防止幻读。如果 WHERE 条件使用了索引,InnoDB 会通过索引锁定对应的行;如果没有索引,则可能升级为表级锁。而 MyISAM 引擎无论是否有 WHERE 条件,都会对整个表加 写锁(排他锁)。