mysql 锁知识汇总

目录

  • 一、锁
    • [1.1 什么是锁?](#1.1 什么是锁?)
    • [1.2 全局锁](#1.2 全局锁)
      • [1.2.1 定义](#1.2.1 定义)
      • [1.2.2 应用场景](#1.2.2 应用场景)
      • [1.2.3 会出现的问题](#1.2.3 会出现的问题)
      • [1.2.4 解决方法](#1.2.4 解决方法)
    • [1.3 表级锁](#1.3 表级锁)
      • [1.3.1 表锁](#1.3.1 表锁)
      • [1.3.2 元数据锁(MDL)](#1.3.2 元数据锁(MDL))
      • [1.3.3 意向锁](#1.3.3 意向锁)
      • [1.3.4 AUTO-INC锁](#1.3.4 AUTO-INC锁)
    • [1.4 行级锁](#1.4 行级锁)
      • [1.4.1 记录锁(Record Lock)](#1.4.1 记录锁(Record Lock))
      • [1.4.2 间隙锁(Gap Lock)](#1.4.2 间隙锁(Gap Lock))
      • [1.4.3 Next-Key Lock(记录锁+间隙锁)](#1.4.3 Next-Key Lock(记录锁+间隙锁))
      • [1.4.4 插入意向锁](#1.4.4 插入意向锁)

一、锁

1.1 什么是锁?

**锁是用来控制对数据库中数据访问的机制。**在并发环境下,多个用户可能同时访问相同的数据,这样就会产生数据的冲突和不一致的情况,为了避免这种情况发生,MySQL提供了多种锁机制。

1.2 全局锁

1.2.1 定义

全局锁就是对整个数据库实例加锁。

MySQL提供了一个加全局读锁的方法,命令是:flush tables with read lock,执行后,整个数据库就处于只读状态了。

1.2.2 应用场景

全库逻辑备份。这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。

1.2.3 会出现的问题

加上全局锁,意味着整个数据库都是只读状态。

  • 那么如果数据库里有很多数据,备份就会花费很多的时间,关键是备份期间,业务只能读数据,而不能更新数据,这样会造成业务停滞。
  • 若从库备份,则在备份期间无法执行主库同步的binlog,则会导致主从延迟。

1.2.4 解决方法

前提:数据库的引擎支持的事务支持可重复读的隔离级别。例如Innodb,MyiSam不支持事务,所以只能全局锁。

mysqldump是官方的逻辑备份工具。当mysqldump使用参数-single-transaction时,将在导数据之前启动事务,由于MVCC的支持,数据可以在这个过程中正常更新。single-transaction仅适用于所有表使用事务引擎的库。

1.3 表级锁

1.3.1 表锁

  • 表共享读锁:lock tables t_student read;//表级别的共享锁,也就是读锁;读锁会阻塞写。
  • 表独占写锁:lock tables t_stuent write;//表级别的独占锁,也就是写锁;写锁会阻塞写和读 。
  • 释放锁:unlock tables;释放当前会话的所有表锁

1.3.2 元数据锁(MDL)

MDL不需要显式使用,数据库自动调用

对一张表进行 CRUD 操作时,加的是 MDL 读锁;

对一张表做结构变更操作的时候,加的是 MDL 写锁;

MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更

当有线程在执行 select 语句( 加 MDL 读锁)的期间,如果有其他线程要更改该表的结构( 申请 MDL 写锁),那么将会被阻塞,直到执行完 select 语句( 释放 MDL 读锁)。

反之,当有线程对表结构进行变更( 加 MDL 写锁)的期间,如果有其他线程执行了 CRUD 操作( 申请 MDL 读锁),那么就会被阻塞,直到表结构变更完成( 释放 MDL 写锁)。
注意:事务执行期间,MDL 是一直持有的 。开启长事务的同时其他事务变更表字段(MDL写锁 ),长事务不及时提交,会导致之后的所有操作都被阻塞。

MDL写锁优先级大于MDL读锁

1.3.3 意向锁

在使用 InnoDB 引擎的表里对某些记录加上「共享锁/独占锁(行锁)」之前,需要先在表级别加上一个「意向共享锁/意向独占锁」;

为什么会有意向锁?

表锁和行锁是满足读读共享、读写互斥、写写互斥的。

没有意向锁:加「独占表锁」时,就需要遍历表里所有记录,查看是否有记录存在独占行锁,这样效率会很慢。

意向锁:加「独占表锁」时,直接查该表是否有意向独占锁。

所以,意向锁的目的是为了快速判断表里是否有记录被加锁

1.3.4 AUTO-INC锁

主键自增使用的就是AUTO-INC锁

在插入数据时,会加一个表级别的 AUTO-INC 锁,然后为被 AUTO_INCREMENT 修饰的字段赋值递增的值,等插入语句执行完成后,才会把 AUTO-INC 锁释放掉。

AUTO-INC 锁是特殊的表锁机制,锁不是再一个事务提交后才释放,而是再执行完插入语句后就会立即释放。

但是, AUTO-INC 锁再对大量数据进行插入的时候,会影响插入性能,因为另一个事务中的插入会被阻塞。
轻量级的锁:在插入数据时,给该字段赋值一个自增的值后,直接释放,不再等待整条语句执行完毕。

1.4 行级锁

InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。

共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。

1.4.1 记录锁(Record Lock)

只将当前数据加锁

S锁与X锁不兼容,X锁与X锁不兼容

1.4.2 间隙锁(Gap Lock)

锁定一个范围,但是不包含记录本身(左开右开区间)

只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。

间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的。

1.4.3 Next-Key Lock(记录锁+间隙锁)

锁定一个范围,并且锁定记录本身(左开右闭区间)

next-key lock 是包含间隙锁+记录锁的,如果一个事务获取了 X 型的 next-key lock,那么另外一个事务在获取相同范围的 X 型的 next-key lock 时,是会被阻塞的(XX互斥)。

1.4.4 插入意向锁

一个事务在插入一条记录的时候,需要判断插入位置是否已被其他事务加了间隙锁(next-key lock 也包含间隙锁)。

如果有的话,插入操作就会发生阻塞,在此期间会生成一个插入意向锁

插入意向锁名字虽然有意向锁,但是它并不是意向锁,它是一种特殊的间隙锁,属于行级别锁

相关推荐
一勺菠萝丶9 分钟前
MongoDB 常用操作指南(Docker 环境下)
数据库·mongodb·docker
Kai HVZ1 小时前
python爬虫----爬取视频实战
爬虫·python·音视频
古希腊掌管学习的神1 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
m0_748244831 小时前
StarRocks 排查单副本表
大数据·数据库·python
B站计算机毕业设计超人1 小时前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
路人甲ing..1 小时前
jupyter切换内核方法配置问题总结
chrome·python·jupyter
C++忠实粉丝1 小时前
Redis 介绍和安装
数据库·redis·缓存
游客5201 小时前
opencv中的常用的100个API
图像处理·人工智能·python·opencv·计算机视觉
wmd131643067121 小时前
将微信配置信息存到数据库并进行调用
数据库·微信
是阿建吖!2 小时前
【Linux】基础IO(磁盘文件)
linux·服务器·数据库