mysql 中的锁

一.锁的介绍

锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,除了传统的计算资源(cpu,ram,i/o)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题。锁冲突也是影响数据库并发访问性能的一个重要因素。

二.mysql锁的分类

三.mysql中锁的介绍

mysql中的锁,按照锁的粒度分可以分为

全局锁:锁定数据库中的所有表

3.1什么是全局锁

全局锁是针对整个数据库的锁。(我的理解就是一个数据库锁,锁的就是整个数据库)

全局锁里面又分为读锁和写锁。

读锁(共享锁):可以多个线程来读取数据,但是不可写入数据。

写锁(排他锁):不允许其他线程来读取和写入数据。

3.2 应用场景

dump表中所有数据的时候可以加入全局锁,保证数据的一致性。

利用mvcc机制也同样可以实现数据dump,但是不用加锁

3.3 全局锁具体示例

开启读锁:flush tables with read lock;

开启读锁,其他线程不可以 修改操作,阻塞中或报错,查询可以

释放锁后可以修改成功

表级锁: 每次操作锁住整张表。

3.1什么是表级锁

每次操作锁住整张表,开销小,加锁快,不会出现死锁,锁定的粒度大,发生锁冲突的概率最高,并发低。

表级锁里面又分为表共享读锁和表独占写锁。

表共享读锁 :{读锁(共享锁)}:可以多个线程来读取数据,但是不可写入数据。

表独占写锁 : {写锁(排他锁)}:不允许其他线程来读取和写入数据。

3.2 应用场景

1.读密集型的场景

2.写操作不是很密集的场景

3.3 表级锁具体演示

1.执行 alter table;

2.执行drop table 或者 truncate table;

3.lock tables t1 write,t2 read.

以上命令给表1加上写锁,给表2 加上读锁。

开启读锁的效果:

开启写锁

查看 锁的状态:show open tables where in_use > 0;

总结:

在同一个客户端中:

开启表的读锁,不可以进行修改,只可以查询

开启表的写锁,可以修改,可以查询

在不同的客户端中:

开启表的读锁,不可以进行修改,只可以查询

开启表的写锁,不可以修改,不可以查询

开启表的写锁:下面是在不同的客户端中查询阻塞

缺点:并发性能下降。

行级锁:每次操作锁住对应的行数据。

3.1什么是行级锁

锁定的是数据的一行,粒度小,能提供更好的并发性,需要更多的资源。

行级锁里面又分为共享锁和排他锁。

共享锁 :{读锁(共享锁)}:可以多个线程来读取数据,但是不可写入数据。

排他锁 :{写锁(排他锁)}:不允许其他线程来读取和写入数据。

3.2使用场景

1.高并发

2.遇到事物的操作

查看那些是行级锁:select * from performance_schema.data_locks;

行级锁, 如果不在事物中执行,语句执行完毕,锁释放

在事物中执行,在没有commit之前这个排他锁一直存在

案例演示:

执行排他锁(写锁):select ... for update

第一个窗口开始事物,设置排他锁

第二个窗口可以查询,不可以修改

执行共享锁(读锁):select......lock in share mode

第一个窗口开启 事物,开启共享锁

第二个窗口 可以查询,不可以修改

总结: 开启行的共享锁和排他锁不同窗口都可以读,不可以修改。

造成的问题:

  1. 在多个事物当中会发生死锁(事物可以理解为多个线程)。

2.锁升级 (锁定多行后,发现还不如锁定整个表)

3.不同的事物隔离级别会影响锁的性能和行为,根据具体的场景来调整事物隔离级别。

按照锁的状态范围分类

共享意向锁

排他意向锁

意向锁个人理解就是一个"信号标记性能锁",以前要去一行一行遍历表中的数据,判断是否存在行锁,现在去看一下,信号标记就可以。

概念 :意向锁是表锁,为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存。

作用:当有事物(线程)A有行锁时,mysql会自动为该表添加意向锁,事物(线程)b如果想申请整个表的写锁,那么不需要遍历每一行判断是否存在行锁,而直接判断是否存在意向锁,增强性能。

查看那些是行级锁:select * from performance_schema.data_locks;

案例演示:

1.第一个窗口开启事物,并开启排他锁

2.查看当前的锁

查看LOCK_TYPE,LOCK_MODE 第一个是表级的意向排他锁 lX显示为排他锁

X是排他锁 LOCK_TYPE显示为 record 行级别。

3.在另一个窗口中添加写锁是阻塞状态:

总结:

间隙锁(范围锁)

和临界锁类似,是一个范围锁。两个值之间的空隙加锁。

演示示例:

1.查看当前的表结构

2.开启事物设置间隙锁(查询的id一定要不存在)

3.开启一个窗口,看到 id < 7的可以正常插入,id > 7 < 10的数据插入失败

临界锁

什么是临界锁 next-key 可以理解为一种特殊的间隙锁,也可以理解为一种特殊的算法。通过临界锁可以解决幻读的问题。每个数据行上的非唯一索引列上都会存在一把临界锁,当某个事物持有该数据的临界锁时,会锁住一段左开右闭区间的数据。innodb中行级锁是基于索引实现的,临界锁只与非唯一索引列有关,在唯一索引列上不存在临界锁。(把下面的演示做一遍才理解的更深刻)

演示案例

第一个窗口开启事物设置,设置临界锁为2000,表里面已经有1000的数据,

所以区间是1000-2000

第二个窗口在插入大于1000 小于 2000范围的数据是阻塞状态,插入不进去

发现插入小于1000也处于阻塞状态,拉拉了。一定要是 (**每个数据行上的非唯一索引列上都会存在一把临界锁)**才会有临界锁

mysql锁总结:

|------------|--------------------------------------|-----------------------------|
| mysql中锁的分类 | 可以多事物(线程)操作 | 不可以多事物(线程)操作 |
| 数据库锁(全局锁) | 读锁 | 写锁 |
| 表级锁 | 共享 lock tables t2 read. | 排他 lock tables t1 write; |
| 行级锁 | 共享锁 select ..... lock in share mode; | 排他锁 select..... for update; |

共享锁 ,读锁 都可以理解为 共享读锁

排他锁 ,写锁 都可以理解为 排他写锁

间隙锁是innodb引擎为了解决幻读,临界锁也是为了解决幻读。

参考:阿里一面:MySQL锁你了解吗?说一下什么是mysql间隙锁?招架不住啊。。_哔哩哔哩_bilibili

相关推荐
柒小毓2 分钟前
将excel导入SQL数据库
数据库
bug菌¹7 分钟前
滚雪球学Oracle[2.5讲]:数据库初始化配置
数据库·oracle·数据库初始化·初始化配置
一休哥助手14 分钟前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
翔云12345622 分钟前
MVCC(多版本并发控制)
数据库·mysql
代码敲上天.39 分钟前
数据库语句优化
android·数据库·adb
盒马盒马1 小时前
Redis:zset类型
数据库·redis
静听山水1 小时前
mysql语句执行过程
数据库·mysql
虽千万人 吾往矣1 小时前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
Q_w77422 小时前
一个真实可用的登录界面!
javascript·mysql·php·html5·网站登录
mariokkm2 小时前
Django一分钟:在Django中怎么存储树形结构的数据,DRF校验递归嵌套模型的替代方案
数据库·django·sqlite