# 锁
## 什么是数据库的锁?有哪些类型?
#### 简要回答
1. **全局锁:** 锁住整个数据库实例,使数据库**只读**,用于**全库备份**。
2. 表级锁:
锁住整张表。
- **表锁:** 最基本的表级锁,MyISAM 存储引擎默认使用。
- **元数据锁:** 保护表结构等**元数据**,避免 DDL 和 DML 冲突。
- **意向锁:** 表明事务即将对行加锁,协调表锁和行锁。
- **AUTO-INC 锁:** 控制**自增列并发插入**的表级锁。
3. 行级锁:
锁住表中的行,开销大,并发度高,InnoDB 中实现了行级锁。
- **Record Lock:** 锁住**单条**索引记录。
- **Gap Lock :** 锁住索引记录之间的间隙,**防止幻读**。
- **Next-Key Lock :** **记录锁和间隙锁的组合**,锁住记录和之前的间隙。
- **插入意向锁 :** **特殊的间隙锁**,表示插入新记录的意图。
------
#### 详细回答
1. 全局锁:
- 全局锁是对整个数据库实例加锁。最典型的应用场景是进行**全库的逻辑备份**。
- 通过执行 `FLUSH TABLES WITH READ LOCK` (FTWRL) 命令,可以使整个数据库处于**只读状态**,阻止所有对数据的修改操作(包括 INSERT, DELETE, UPDATE 以及大部分 DDL 语句)。这样可以确保备份期间数据的**一致性**。
- 释放全局锁可以使用 `UNLOCK TABLES` 命令或客户端断开连接。
2. 表级锁:
直接锁住整张表。
- **表锁 (Table Lock):** ① 是最基本的表级锁,可以通过 `LOCK TABLES` 命令**显式地**对表加锁,例如 `LOCK TABLES table_name READ` (表读锁) 或 `LOCK TABLES table_name WRITE` (表写锁)。 ② 表锁**开销最小**,但会严重**降低并发度**,因为会阻塞对该表的其他所有读写操作。MyISAM 存储引擎默认使用表锁。
- **元数据锁 (Metadata Lock / MDL):** ① MDL 是在访问数据库对象(如表、视图、存储过程等)时**自动添加**的锁。 ② 它的主要作用是保证在执行 DDL 操作时,不会与正在进行的 DML 操作发生冲突,反之亦然。例如,当一个事务正在读取表数据时,如果另一个会话尝试修改表结构,就会被 MDL 阻塞,直到读事务完成。
- **意向锁 (Intention Lock):** ① 意向锁是 InnoDB 存储引擎**自动添加的表级锁**。 ② 它用于表示一个事务**即将**对表中的行加**共享锁(IS Lock)** 或 **排他锁(IX Lock)** 。 ③ 意向锁的存在是为了提高行级锁和表级锁的兼容性判断效率。当一个事务尝试加表级共享锁或排他锁时,**只需要检查表上是否存在意向锁**,而无需遍历所有行检查是否存在行级锁。
- **AUTO-INC 锁 (自增锁):** ① AUTO-INC 锁是一种特殊的表级锁,在向**包含自增列**的表中插入数据时使用。 ② 它用于保证在**并发插入**的情况下,自增值能够**唯一且连续**地生成。在插入完成后,自增锁会立即释放。 ③ 在不同的 `innodb_autoinc_lock_mode` 配置下,自增锁的行为会有所不同,以平衡并发度和自增值的连续性。
3. 行级锁:
只锁住表中的某一行或某些行。行级锁开销较大,但能显著提高并发度。行级锁主要由 InnoDB 存储引擎实现。
- **记录锁 (Record Lock):** ① 记录锁**也称为行锁**,它锁住的是索引记录。 ② 当一个事务对某条记录进行**修改或删除**时,会加**排他记录锁**;当一个事务对某条记录进行**读取**(在特定隔离级别下)时,会加**共享记录锁**。
- **间隙锁 (Gap Lock):** ① 间隙锁是 InnoDB 在可重复读 (REPEATABLE READ) 隔离级别下为了防止**幻读**而引入的一种锁。 ② 它锁住的是**索引记录之间的间隙,而不是记录本身**。间隙锁之间是兼容的,但会阻塞其他事务在被锁的间隙中插入记录。
- **临界锁 (Next-Key Lock):** ① 临界锁是 **InnoDB 默认的行锁类型**,它是**记录锁和间隙锁的组合**,锁住的是**索引记录以及该记录之前的间隙**。 ② 临界锁在可重复读隔离级别下使用,既能防止幻读,也能保证索引记录的唯一性。
- **插入意向锁 (Insert Intention Lock):** ① 插入意向锁是一种**特殊的间隙锁**,它在事务执行 INSERT 操作时产生。 ② 当多个事务在同一个间隙中插入记录时,如果它们插入的位置不冲突,它们可以同时持有插入意向锁,而无需互相等待。 ③ 插入意向锁表示了事务在某个间隙中插入记录的**意图**,但不会阻塞其他事务在该间隙中插入记录(除非有冲突的间隙锁)。
------
#### 知识拓展
1. MySQL常见的锁类型
,示意图如下:

2. 面试官可能的追问1:InnoDB 的行级锁是如何实现的?
- **简答:** InnoDB 的行级锁是基于**索引**实现的。它通过在索引记录上加锁来锁定对应的行。如果没有索引,InnoDB 会使用隐藏的聚簇索引来加锁,这可能会导致全表扫描并加锁,降低并发度。
3. 面试官可能的追问2:间隙锁主要解决了什么问题?在哪些隔离级别下会使用?
- **简答:** 间隙锁主要解决了**幻读**问题。幻读是指在同一个事务中,两次执行相同的查询语句,第二次查询结果包含了第一次查询没有的记录。间隙锁通过锁住索引记录之间的间隙,防止其他事务在间隙中插入记录,从而避免幻读。间隙锁主要在 **可重复读 (REPEATABLE READ)** 隔离级别下使用。
4. 面试官可能的追问3:意向锁的作用是什么?它是如何协调表锁和行锁的?
- **简答:** 意向锁是一种表级锁,用于表示事务即将对表中的行加锁。当一个事务尝试加表级共享锁或排他锁时,MySQL 会检查表上是否存在意向锁。如果存在意向排他锁,则不能加表级共享锁或排他锁;如果存在意向共享锁,则不能加表级排他锁。通过意向锁,可以在表级快速判断是否存在行级锁,避免遍历所有行进行检查,提高了锁的兼容性判断效率。
## MySQL中的锁等待和死锁是什么?如何处理?
- **锁等待**:当一个线程请求锁定某个资源时,如果资源已被其他线程锁定,该线程会进入等待状态,直到资源释放。锁等待是正常的并发访问的一部分。
- **死锁**:死锁是指多个线程互相持有对方需要的锁,导致它们无法继续执行。死锁会造成资源的无限等待和程序阻塞。
- 处理方法
:-
死锁检测
:MySQL会自动检测死锁并回滚其中一个事务来打破死锁。-
死锁预防
:通过合理设计事务的执行顺序、减少锁的粒度或使用较低的事务隔离级别来预防死锁。
- **锁等待超时**:设置锁等待超时,防止长时间等待锁的情况。
## 解释一下数据库的隔离级别与锁的关系?
#### 隔离级别
数据库提供的隔离级别有读未提交、读已提交、可重复读、串行化,四个级别,用来解决脏读、可重复读和幻读的问题。 脏读:事务在执行过程中,还未提交,但被另一个事务读到了数据 不可重复读:事务在执行过程中,先后两次读取同一条记录获得的数据不一致, 幻读:针对的是记录的集合,先后获取同一集合的数据,结果不一致
#### 锁的种类
全局锁、表锁和行锁
#### 关系
读已提交:只允许读已提交的数据,对记录加行锁,即记录锁,来解决脏读,但可能发生可重复读的问题 可重复读:保证在同一个事务中多次读取同一数据集合时,保持不变。通过MVCC保证了可重复读(能够感知到数据的修改),间隙锁保证了不会发生幻读(能够防止整行数据的掺入删除)。 串行化:事务串行执行,避免了所有并发问题,同时性能也是最差的
## 解释一下数据库的悲观锁和乐观锁?
**悲观锁(Pessimistic Lock)**
- **概念**:悲观锁假设并发操作会经常发生冲突,因此在数据读取时就上锁,防止其他事务修改或读取数据,直到事务完成。
- **使用场景**:- 高并发且冲突频繁的环境。- 需要严格的数据一致性和完整性的场景,如银行转账系统。
- **实现方式**:- 在SQL中使用`SELECT ... FOR UPDATE`语句。- 数据库层面的锁机制,如行锁、表锁。
**乐观锁(Optimistic Lock)**
- **概念**:乐观锁假设并发冲突不常发生,因此在数据读取时不加锁,而是在数据更新时检查是否有其他事务修改过数据,如果有冲突则回滚或重试。
- **使用场景**:- 低并发或冲突较少的环境。- 对性能要求较高,且可以接受一定程度的数据重试。
- **实现方式**:- 使用版本号(如`version`字段)或时间戳,在更新时检查版本号是否一致。- 基于应用层的实现,如CAS(Compare-And-Swap)操作。
**总结**:
- 悲观锁适用于高并发且冲突频繁的场景,确保数据的一致性,但可能影响性能。
- 乐观锁适用于并发冲突较少的场景,提升性能,但需要处理可能的冲突。
## 什么是数据库的行级锁和表级锁?有什么区别?
数据库锁主要解决的是多事务并发时的数据一致性问题。作用是避免多个事务同时修改同一数据导致的数据损坏、确保事务执行不受其他事务干扰(如脏读、幻读)。
**按锁定范围划分**,锁的类型分为行级锁、页级锁、表级锁、数据库级锁;**按访问权限划分**,分为共享锁、排他锁、意向锁;**按锁定策略划分**,分为乐观锁、悲观锁、MVCC;还有一些其他的**特殊锁机制**,例如间隙锁、自增锁。