# MySQL锁机制

> 来源：梦飞idc云平台 | 原文：https://www.mfisp.com/9715.html | 发布：2022-09-06 | 更新：2022-09-06 | 分类：建站教程、投稿分享

![MySQL锁机制](https://www.mfisp.com/wp-content/uploads/2022/02/1397fb3628f64c1_1_post.jpg)

 

### 1 锁的类型

 

#### 1.1 行级锁

 

MySQL提供两种标准级别的行级锁

 
 
- 共享锁 (S Lock)：允许事务读取一行数据 
- 排他锁 (X Lock)：允许事务删除或更新一行数据 

 

排他锁与共享锁的兼容性

 

#### 1.2 意图锁

 

InnoDB支持**多细粒度锁定**，允许在行级上的锁和表级上的锁同时存在

 

InnoDB还支持额外的锁方式，称之**意向锁**，是**表**级别的锁，用于在一个事务中揭示下一行将被请求的锁的类型

 
 
- 意向共享锁(IS Lock)：事务想获取表中某几行的共享锁 
- 意向排他锁(IX Lock)：事务想获取表中某几行的排他锁 

 

意图锁需遵循以下协议：

 
 
- 在事务获取某行的共享锁前，首先需获取IS锁或更强的锁 
- 在事务获取某行的独占锁前，首先在表上获取IX锁 

 

|  | **IS** | **IX** | **S** | **X** |
|---|---|---|---|---|
| **IS** | 兼容 | 兼容 | 兼容 | 不兼容 |
| **IX** | 兼容 | 兼容 | 不兼容 | 不兼容 |
| **S** | 兼容 | 不兼容 | 兼容 | 不兼容 |
| **X** | 不兼容 | 不兼容 | 不兼容 | 不兼容 |

 

X锁与任何的锁都不兼容，S锁与IX锁不兼容，剩下的均兼容

 

意向锁只会阻塞表级别的锁，并不会阻塞行级别的锁

 

InnoDB存储引擎的两种加锁操作：

 
 
- select … for update：对读取的行加一个X锁，其他事务加锁将会被阻塞 
- select … lock in share mode：对读取的行记录加一个S锁，其他事务可以加S锁，但对于X锁将会被阻塞 

 

#### 1.3 自增锁

 

事务插入到具有AUTO-INC列的一种特殊表级锁，当事务插入时，必须获取自增锁以获取自增列的值

 

innodb_autoinc_lock_mode参数

 
 
- 值0：在5.1版本之前的自增长实现方式，通过表锁的AUTO-INC Locking方式 
- 值1(默认)：对于Simple Inserts，使用互斥量对内存的计数器进行累加，对于Bulk Inserts，使用传统表锁的AUTO-INC Locking方式 
- 值2：此模式任何时候都可以使用Row-Base Replication，保证了最大并发性能和Replication数据的同步 

 

#### 1.4 外键的锁机制

 

外键的插入更新需先查询父表记录，若该行记录被另一个事务加X锁未提交，则后续插入操作首先会加入S锁，则插入操作会被阻塞，提交后也会产生数据不一致的情况

 

### 2 锁算法

 

InnoDB三个行锁算法：

 
 
- Record Lock： 单行记录的锁 
- Gap Lock：间隙锁，锁定一个范围，不包含记录本身 
- Next-Key Lock：锁定一个范围，包含记录本身，在可重复读隔离级别下的默认行记录锁定算法 

 

### 3 锁问题

 
 
- **丢失更新**

 

多个事务同时修改某个行数据，导致某个事务的修改被覆盖 
- **脏读**

 

脏数据概念：缓冲区已被修改的页，尚未刷写会磁盘的数据

 

脏读：不同的事务下，读取到其他事务未提交的数据，存在于读未提交隔离级别下 
- **不可重复读**

 

同一个事内，若数据被另一个事务修改提交，会导致两次读取的数据不一致，违反了事务一致性的原则

 

在InnoDB里，通过Next-Key Lock算法避免了不可重复读的问题，在mysql里定义为Phantom Problem(幻读)，Next-key算法会锁定扫描到的以及间隙，避免了范围内的插入操作，避免了不可重复读的问题 

 

### 4 阻塞

 

一个事务中的锁需要等待另一个事务中的锁释放占用的资源，使用mutex数据结构实现阻塞机制

 

InnoDB使用参数innodb_lock_wait_timeout控制锁的等待时间，参数innodb_rollback_on_timeout设定是否进行回滚，默认OFF表示不回滚，lock参数可在数据库运行时动态调整，而rollback参数是静态的，仅可以在启动时调整

 

### 5 死锁

 

数据库在并行情况下可能会发生死锁，存在于两种资源之间的相互等待

 

InnoDB在侦测到死锁后，会回滚事务。如oracle，死锁多发生于未对外键添加索引，而InnoDB引擎会自动进行添加，不可人为删除外键索引，因此较好的解决了这种问题

 

### 6 锁升级

 

定义：将当前锁的粒度降低，例如把一个表的100个行锁升级成一个页锁，或页锁升级成表锁，为避免锁的开销，会频繁出现锁升级的现象

 

mssql在05版之后支持行锁，当一条SQL在一个对象的锁数量超过阈值5000或锁资源占用的内存超过40%会发生锁升级

 

InnoDB中不存在锁升级的问题，MySQL里锁的开销与数量无关，类似Oracle的设计

---
本页由 梦飞idc云平台（https://www.mfisp.com）提供。站点导航见 https://www.mfisp.com/llms.txt
