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

相关推荐
he258194 分钟前
centOS 7.9 安装JDK MYSQL
java·mysql·centos
夜泉_ly2 小时前
MySQL -安装与初识
数据库·mysql
qq_529835353 小时前
对计算机中缓存的理解和使用Redis作为缓存
数据库·redis·缓存
月光水岸New6 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6756 小时前
数据库基础1
数据库
我爱松子鱼6 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo6 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser7 小时前
【SQL】多表查询案例
数据库·sql
Galeoto7 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
人间打气筒(Ada)8 小时前
MySQL主从架构
服务器·数据库·mysql