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

相关推荐
悟能不能悟3 小时前
springboot在DTO使用service,怎么写
java·数据库·spring boot
达瓦里氏1233 小时前
重排反应是什么?从分子变化到四大关键特征解析
数据库·学习·化学
电话交换机IPPBX-3CX3 小时前
Grafana图表与电话交换机的结合
数据库·mysql·grafana·ip pbx·电话交换机
IT 小阿姨(数据库)3 小时前
PostgreSQL REST API 介绍
运维·数据库·sql·postgresql·centos
.YYY4 小时前
MySQL--DQL(1)
数据库·mysql
叫我龙翔4 小时前
【MySQL】从零开始了解数据库开发 --- 基本查询
android·mysql·数据库开发
盖世英雄酱581364 小时前
分库分表正在被淘汰
数据库·后端
ClouGence5 小时前
轻量安全、开箱即用:0 成本开启数据实时同步
数据库·saas
junnhwan5 小时前
【苍穹外卖笔记】Day05--Redis入门与店铺营业状态设置
java·数据库·redis·笔记·后端·苍穹外卖