MySQL的锁有哪些类型

基于锁的属性分类:共享锁(读锁)、排他锁(写锁)
基于锁的粒度分类:行级锁((innodb )、表级锁( innodb、myisam)、页级锁( innodb引擎)、记录锁、间隙锁、临键锁
基于锁的状态分类:意向共享锁、意向排它锁(一般不用)。

按属性分:
共享锁(share lock):共享锁又称读锁,简称S锁;当一个事务为数据加上读锁之后,其他事务只能对该数据加读锁,而不能对数据加写锁,直到所有的读锁释放之后其他事务才能对其进行加持写锁。共享锁的特性主要是为了支持并发的读取数据,读取数据的时候不支持修改,避免出现重复读的问题


排他锁(exclusive lock)︰排他锁又称写锁,简称×锁;当一个事务为数据加上写锁时,其他请求将不能再为数据加任何锁,直到该锁释放之后,其他事务才能对数据进行加锁。排他锁的目的是在数据修改时候,不允许其他人同时修改,也不允许其他人读取,避免了出现脏数据和脏读的问题
 

按粒度分:
行锁:行锁是指上锁的时候锁住的是表的某一行或多行记录,其他事务访问同一张表时,只有被锁住的记录不能访问,其他的记录可正常访问,特点:粒度小,加锁比表锁麻烦,不容易冲突,相比表锁支持的并发要高

表锁(table lock):表锁是指上锁的时候锁住的是整个表,当下一个事务访问该表的时候,必须等前一个事务释放了锁才能进行对表进行访问;特点:粒度大,加锁简单,容易冲突;


页锁:页级锁是MysQL中锁定粒度介于行级锁和表级锁中间的一种锁.表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。特点:开销和加锁时间界于表锁和行锁之间,会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。


记录锁(Record lock):记录锁也属于行锁中的一种,只不过记录锁的范围只是表中的某一条记录,记录锁是说事务在加锁后锁住的只是表的某一条记录,加了记录锁之后数据可以避免数据在查询的时候被修改的重复读问题,也避免了在修改的事务未提交前被其他事务读取的脏读问题


间隙锁:是属于行锁的一种,间隙锁是在事务加锁后其锁住的是表记录的某一个区间,当表的相邻ID之间出现空隙则会形成一个区间,遵循左开右闭原则。范围查询并且查询未命中记录,查询条件必须命中索引、间隙锁只会出现在REPEATABLE_READ(重复读)的事务级别中。


临键锁(Next-Key lock):也属于行锁的一种,并且它是INNODB的行锁默认算法,总结来说它就是记录锁和间隙锁的组合,临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住
再之它会把相邻的下一个区间也会锁住。

 

<think>我们正在回答用户关于MySQL类型的问题。根据用户提供的引用内容,我们可以整理出MySQL中支持的类型及其用途。注意,用户引用的内容主要涉及InnoDB存储引擎的机制,因为InnoDB是MySQL最常用的存储引擎,且支持行级。 根据引用[2]、[3]、[4]、[5]的内容,我们可以将MySQL中的类型按不同维度分类: 1. **按的粒度分类**:全局、表级、行级。 2. **按的兼容性分类**:共享(S)、排他(X)、意向共享(IS)、意向排他(IX)。 3. **按的实现机制分类**:记录(Record Locks)、间隙(Gap Locks)、临键(Next-Key Locks)。 下面我们详细说明每种的用途: ### 一、按的粒度分类 #### 1. 全局(Global Lock) - **用途**:定整个数据库实例,禁止任何写入操作,用于全库备份等场景。 - **实现方式**:执行`FLUSH TABLES WITH READ LOCK`命令。 - **特点**:阻塞所有写操作,但读操作(如SELECT)可以继续(因为读操作使用MVCC快照)[^4]。 #### 2. 表级(Table-Level Locks) - **用途**:定整张表,分为表和元数据(MDL)。 - **类型**: - **表(Table Lock)**: - 通过`LOCK TABLES ... READ/WRITE`手动加。 - 读(共享):允许其他会话读,但不允许写。 - 写(排他):禁止其他会话读写。 - **元数据(Metadata Lock, MDL)**: - 自动加,用于防止DDL操作与DML操作冲突(如防止在查询过程中表结构被修改)[^4]。 - 例如:当一个事务对表进行查询(SELECT)时,会加MDL读;当执行ALTER TABLE时,会加MDL写。 #### 3. 行级(Row-Level Locks) - **用途**:定单行或多行数据,实现高并发下的精细控制(InnoDB特有)[^2][^3]。 - **类型**: - **记录(Record Locks)**: - 定索引中的一条具体记录(即使表无索引,InnoDB也会创建隐藏聚簇索引)。 - 例如:`SELECT * FROM t WHERE id=1 FOR UPDATE;` 会定id=1的行[^2]。 - **间隙(Gap Locks)**: - 定索引记录之间的间隙(不包括记录本身),防止其他事务在范围内插入新数据。 - 例如:`SELECT * FROM t WHERE id>10 AND id<20 FOR UPDATE;` 会定(10,20)的区间[^3][^4]。 - **临键(Next-Key Locks)**: - 记录+间隙的组合,定一个左开右闭的区间(如(10,20])。 - 默认行模式,用于解决幻读问题(RR隔离级别下)[^2][^4]。 - **插入意向(Insert Intention Locks)**: - 一种特殊的间隙,表示事务准备在某个间隙插入数据(不会阻塞相同间隙的插入意向)[^3]。 ### 二、按的兼容性分类 | **类型** | **缩写** | **用途** | **兼容性** | |------------|----------|--------------------------------------|----------------------------------------------------------------------------| | **共享** | S | 允许其他事务读,但禁止写(如SELECT ... LOCK IN SHARE MODE) | 与S、IS兼容;与X、IX冲突[^5] | | **排他** | X | 禁止其他事务读写(如SELECT ... FOR UPDATE) | 与所有冲突(除IS在某些情况下兼容外)[^5] | | **意向共享** | IS | 事务计划对某些行加S(表级) | 与IX、S部分兼容(具体见兼容性表)[^3] | | **意向排他** | IX | 事务计划对某些行加X(表级) | 与IS兼容,与其他IX兼容(但会阻塞X)[^3] | > 📌 **兼容性矩阵**(表级)[^4]: > | 请求 \ 现有 | X | IX | S | IS | > |----------------|-----|-----|-----|-----| > | **X** | 冲突 | 冲突 | 冲突 | 冲突 | > | **IX** | 冲突 | 兼容 | 冲突 | 兼容 | > | **S** | 冲突 | 冲突 | 兼容 | 兼容 | > | **IS** | 冲突 | 兼容 | 兼容 | 兼容 | ### 三、与隔离级别的关系 不同隔离级别使用不同的策略[^4]: 1. **读未提交(Read Uncommitted)**:不加,通过脏读实现(实际生产环境极少使用)。 2. **读已提交(Read Committed)**:使用记录,无间隙(可能发生幻读)。 3. **可重复读(Repeatable Read)**:默认使用临键(Next-Key Lock),解决幻读问题。 4. **串行化(Serializable)**:所有读操作加共享,写操作加排他(相当于表级)。 ### 四、死处理 - **检测机制**:InnoDB通过等待图(Wait-for Graph)检测死[^4]。 - **处理策略**:强制回滚代价较小的事务(如undo log量少的事务),释放其资源。 ### 五、监控工具 1. `SHOW ENGINE INNODB STATUS`:查看InnoDB引擎状态(含信息)。 2. 信息模式表: - `INNODB_TRX`:当前运行的事务。 - `INNODB_LOCKS`:当前持有的MySQL 8.0已移除,改用`performance_schema.data_locks`)。 - `INNODB_LOCK_WAITS`:等待关系(MySQL 8.0改用`performance_schema.data_lock_waits`)[^4]。 3. 性能模式(Performance Schema):更细粒度的监控。 ### 总结 MySQL机制是保障数据一致性和并发性能的核心组件。理解不同的用途及适用场景,有助于设计高性能、高并发的数据库应用。在实际开发中,应结合业务场景选择合适的隔离级别,并通过索引优化减少冲突(如避免无索引导致的行升级为表)[^2][^3]。 --- ### 相关问题 1. **InnoDB 的间隙(Gap Lock)在什么情况下会失效?如何避免?** 2. **如何通过索引设计优化行级的并发性能?** 3. **MySQL 8.0 在监控方面有哪些改进?如何利用 performance_schema 分析等待问题?** 4. **在可重复读(RR)隔离级别下,临键(Next-Key Lock)是如何解决幻读问题的?** 5. **共享(S)和排他(X)在哪些场景下容易引发死?如何预防?**</think>### MySQL 支持的类型及其用途 MySQL机制按**粒度**可分为全局、表级和行级,按**功能**可分为共享、排他、意向等。以下是详细分类及用途: --- #### 一、按粒度分类 | **类型** | **用途** | **示例/说明** | |----------------|--------------------------------------------------------------------------|------------------------------------------------------------------------------| | **全局** | 定整个数据库实例,禁止所有写操作 | 全库备份场景:`FLUSH TABLES WITH READ LOCK`[^4] | | **表级** | 定整张表 | 手动加:`LOCK TABLES table_name READ/WRITE` | | **行级** | 定单行或多行数据(InnoDB 特有) | 通过索引实现,无索引时退化为表[^3] | --- #### 二、按功能分类(行级细分) | **类型** | **定范围** | **用途** | **隔离级别支持** | |--------------------|----------------------------------|--------------------------------------------------------------------------|----------------------| | **记录** | 单行记录 | 防止其他事务修改或删除当前行 | RC, RR, Serializable | | **间隙** | 索引记录之间的间隙 | 防止幻读(阻止在范围内插入新数据) | RR, Serializable | | **临键** | 记录+间隙(左开右闭区间) | 默认行模式,解决幻读(如定 `(10,20]`) | RR, Serializable | | **插入意向** | 待插入的间隙位置 | 表示事务准备插入数据,不阻塞相同间隙的插入操作 | 所有级别 | > 📌 **间隙示例**: > ```sql > -- 定 id>100 的间隙,阻止插入 id=101 的数据 > SELECT * FROM accounts WHERE id > 100 FOR UPDATE; > ``` --- #### 三、按兼容性分类(表级/行级) | **类型** | **缩写** | **用途** | **兼容性** | |--------------------|----------|--------------------------------------------------------------------------|----------------------------------------------------------------------------| | **共享 (S)** | S | 允许其他事务读,但禁止写(如 `SELECT ... LOCK IN SHARE MODE`) | 与 S、IS 兼容;与 X、IX 冲突[^5] | | **排他 (X)** | X | 禁止其他事务读写(如 `SELECT ... FOR UPDATE`) | 与所有冲突(包括 S、X、IS、IX)[^5] | | **意向共享** | IS | 表示事务计划对某些行加 S(表级) | 与 IX 兼容,与 X 冲突[^3] | | **意向排他** | IX | 表示事务计划对某些行加 X(表级) | 与 IS 兼容,与 S/X 冲突[^3] | > 🔒 **兼容性矩阵**(简化版)[^4]: > | 请求 \ 现有 | X | IX | S | IS | > |----------------|-----|-----|-----|-----| > | **X** | ❌ | ❌ | ❌ | ❌ | > | **IX** | ❌ | ✔️ | ❌ | ✔️ | > | **S** | ❌ | ❌ | ✔️ | ✔️ | > | **IS** | ❌ | ✔️ | ✔️ | ✔️ | --- #### 四、与隔离级别的关系 | **隔离级别** | **使用的机制** | |--------------------|--------------------------------------------------------------------------------| | **Read Committed** | 仅用记录(无间隙),可能发生幻读 | | **Repeatable Read**| 默认使用临键(记录+间隙),通过范围解决幻读[^4] | | **Serializable** | 所有读操作加共享(S),写操作加排他(X),等效表级 | > ⚠️ **关键点**: > - 行依赖索引:无索引时 InnoDB 退化为表[^3] > - 间隙仅在 RR 及以上级别生效 > - 意向(IS/IX)是表级,用于快速检测行冲突[^3] --- #### 五、死处理与监控 1. **死检测**: InnoDB 使用等待图(Wait-for Graph)自动检测死[^4]。 2. **处理策略**: 回滚代价较小的事务(如 undo log 量少的事务)。 3. **监控工具**: ```sql SHOW ENGINE INNODB STATUS; -- 查看和事务信息 SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; -- 当前运行事务 SELECT * FROM PERFORMANCE_SCHEMA.DATA_LOCK_WAITS; -- 等待关系 ``` --- ### 总结 MySQL 通过多粒度(全局、表、行)和多功能(共享、排他、间隙等)实现并发控制。**InnoDB 的行级(记录/间隙/临键)** 是其高并发的核心,尤其在 RR 隔离级别下通过临键解决幻读问题。设计时需注意: 1. 索引优化避免行升级为表 2. 合理选择隔离级别平衡一致性与性能 3. 监控争用避免死 --- ### 相关问题 1. **在 RR 隔离级别下,间隙如何避免幻读?哪些场景下会失效?** 2. **无索引时行为何会退化为表?如何通过索引设计优化性能?** 3. **意向(IS/IX)如何加速冲突检测?与行级的协作机制是什么?** 4. **MySQL 8.0 的 `NOWAIT` 和 `SKIP LOCKED` 选项如何解决等待问题?** 5. **如何通过 `performance_schema` 监控并分析生产环境的争用情况?**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值