MySQL----锁

一、概述

首先为什么需要锁,这是因为在高并发的情况下,如果没有锁,很容易出现脏读,不可重复读,幻读的问题,而锁的合理使用就可以很大程度上避免这些情况,MySQL的锁,在主流的Innodb引擎下,按照锁的粒度分为 全局锁,表级锁,行级锁。全局锁:锁住整个数据库;表级锁:锁住整个表;行级锁:锁住对应的行数据。这些锁,就是MySQL实现不同事务隔离级别的基础。

二、介绍锁

1.全局锁

锁的粒度很大,主要应用场景就是数据库的全局备份,加上全局锁可以保证数据的一致性,保证数据的完整性。加上全局锁后,数据库中还是可以进行select查询的。

语法

加锁:flush tables with read lock;

解锁:Unlock tables;

可以通过使用:

复制代码
mysqldump --single-transation -u+用户名 -p+数据库密码 数据库名 > 文件名.sql;

来实现在不加全局锁的情况下也能完成全局备份。

2.表级锁

表级锁分为3类:

1.表锁

表锁又分为表共享读锁/读锁,表独占写锁/写锁/排他锁,其中加读锁的情况下是所有客户端都只能读不能写,而加写锁的情况下是只有加了写锁的客户端可以读和写,其他客户端都不能进行读写。

语法:

加锁:lock tables 表名 read/write;

解锁:Unlock tables/客户端断开连接。

2.元数据锁

元数据其实就是指数据库中的表结构,当表中有活跃事务时,如果此时进行表结构修改,此时就会因为有元数据锁的存在而失败,元数据锁的存在,就是为了避免DML和DDL语句的冲突。

元数据锁简称MDL,也分为读锁和写锁/排他锁。

在MySQL5.5版本后,当执行DDL语句时,会自动加上MDL读锁,此时不能进行表结构的修改,当执行DML语句时,会自动加上MDL写锁。

3.意向锁

意向锁是用于解决在添加表锁时,需要一行一行的查找是否有活跃事务,从而导致效率过低的情况。意向锁也分为两类:意向共享锁IS,意向排它锁IX。和DML一样,也是自动加锁。

IS:与表锁中的读锁兼容,与表锁中的写锁互斥。由 select ..... lock in share mode;语句触发。

IX:与表锁的读锁和写锁冲突,但是意向锁之间是不互斥的。由 insert,update,delete以及 select....

for update来触发。

我们可以通过以下语句来查看当前数据库中锁的情况:

复制代码
select object_schema,object_name,index_name,
lock_type,lock_mode,lock_data from performance_schema.data_locks;

但是注意一下,在MySQL中,存在隐式提交事务的情况,就是在一个还未提交的事务中进行添加表锁/全局锁时,即使此时存在冲突的意向锁,但是添加表锁或全局锁时会自动提交事务,从而使得意向锁失效,此时仍可以加上表锁。

3.行级锁

行锁在Innodb中是通过对索引上的索引项加锁来实现的,并非是对数据行进行加锁。行级锁是最小粒度的锁,也是并发性能最高的。

分为 行锁,间隙锁,临建锁。

1.行锁

锁定单个行记录的锁,防止其他事务进行update/delete,很显然,它不能解决幻读问题,所以在RR和RC隔离级别中都有。

行锁又分为读锁/共享锁S和写锁/排他锁X,S:允许一个事务去读这一行,但是阻止其他事务来获得X。

X:允许获得锁的事务来更新和查询这一行数据,但是不允许其他事务获得S和X。

不同SQL语句触发的锁

|------------------------------|------|--------|
| SQL语句类型 | 行锁类型 | 获得锁的方式 |
| insert | X | 自动 |
| update | X | 自动 |
| delete | X | 自动 |
| select(普通类型) | 不加锁 | |
| select....lock in share mode | S | 自动 |
| select....for update | X | 自动 |

还有下面两种情况:

1.当针对唯一索引进行检索时,对已经存在的记录进行等值匹配时,会自动优化为行锁。这是因为行锁是和索引息息相关的,如果索引查询出的值唯一且存在,当然会成为行锁。

2.当不通过索引来查询数据时,将会上升为表锁。

2.间隙锁/临建锁

这俩哥们放一块,是因为它们经常相互转换。它们主要是解决幻读问题的,将间隙加上锁,就是让这个区域不能进行insert,在普通索引的情况下,这样有效避免了多次查询结果不一样的情况。间隙锁也是可以共存的。

在RR隔离级别下,Innodb默认使用临建锁。当发生一下情况下时:

1.进行唯一索引的等值查询时,如果给不存在的记录进行加锁时,或优化为间隙锁。将目标索引(如Id)的相邻的两个值之间进行加锁。

2.进行普通索引的等值查询时,因为普通索引可能会重复,所以当向右遍历到最后一个值不满足查询条件时,临建锁会退化为间隙锁。此时就是将目标值到前一个索引和到后一个索引的间隙都加上锁。

3.索引上的范围查询,而且是唯一索引时,会访问到不满足条件的第一个值为止,如果是>的情况,就会将正无穷到条件值都加上间隙锁。

相关推荐
2603_965148115 小时前
如何解析JSON数据?API返回的商品信息处理教程
开发语言·数据库·python·自动化·json·api
ltl5 小时前
RocksDB 经典故障排查:L0、compaction 与 write stall
数据库
xfhuangfu6 小时前
Oracle中建立到CDB和PDB的连接
数据库·oracle·rpc
小小龙学IT6 小时前
DuckDB 深度实战:用 C++ 在进程内跑一个「分析型数据库」
数据库·c++
NineData7 小时前
DTCC 2026 预告|NineData CEO& 创始人叶正盛:面向 AI Agent 的数据库 DevOps 与数据复制实践
数据库·人工智能·数据库开发·devops·ninedata·数据库技术·dtcc
J_bean7 小时前
MySQL 事务是否必须手动开启?
数据库·mysql·数据库事务·自动提交·手动提交
J_bean7 小时前
MySQL InnoDB 如何检测死锁、判定死锁、处理死锁
数据库·mysql·死锁·死锁检测·处理死锁·死锁判定
浪子明X8 小时前
从 MongoDB 文档到关系模型:构建可重跑、可对账的数据迁移流水线
数据库·mongodb·oracle
杜子不疼.8 小时前
国产数据库撑起固井软件自主化:金仓 × 中海油服「海恒 Cemsol」落地解析
数据库
隔窗听雨眠8 小时前
GBase 8s并发控制深度解析:封锁机制、隔离级别与死锁处理全攻略
服务器·数据库·oracle