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 也包含间隙锁)。

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

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

相关推荐
FreakStudio1 小时前
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
python·单片机·嵌入式·面向对象·电子diy
丶21361 小时前
【CUDA】【PyTorch】安装 PyTorch 与 CUDA 11.7 的详细步骤
人工智能·pytorch·python
vvvae12341 小时前
分布式数据库
数据库
_.Switch2 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
雪域迷影2 小时前
PostgreSQL Docker Error – 5432: 地址已被占用
数据库·docker·postgresql
一个闪现必杀技2 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm
小鹿( ﹡ˆoˆ﹡ )2 小时前
探索IP协议的神秘面纱:Python中的网络通信
python·tcp/ip·php
bug菌¹3 小时前
滚雪球学Oracle[4.2讲]:PL/SQL基础语法
数据库·oracle
逸巽散人3 小时前
SQL基础教程
数据库·sql·oracle
卷心菜小温3 小时前
【BUG】P-tuningv2微调ChatGLM2-6B时所踩的坑
python·深度学习·语言模型·nlp·bug