MySQL读写锁(元数据锁、意向锁、行锁、间隙锁、临键锁)

目录

一、概述

锁机制用来保证多线程(同一事务、不同事务之间)并发访问同一行数据引发的数据一致性问题。

MySQL的锁分为以下三类:

  • 全局锁:线程串行访问数据库
  • 表级锁:在一张表上加锁,线程串行访问该表
  • 行级锁:在一行记录上加锁,每次操作锁住对应的行数据

二、全局锁

对整个数据库实例加锁,加锁后其他线程可以读数据库内容,但是创建表、增删改操作会被阻塞

全局锁一般用于备份整个数据库时 使用,防止涉及多表更新的业务 在备份文件中出现数据不一致问题。

数据库备份过程:

  1. 添加全局锁:flush tables with read lock;
  2. 执行备份:mysqldump -h服务器IP地址 -u用户名 -p密码 数据库名 > 备份保存绝对路径D:/.../xxx.sql
  3. 释放锁:unlock tables;

备份后数据会发生变化,所以可以参考redis将备份后执行的MySQL指令记录下来,便于数据库宕机后使用指令日志和备份文件恢复数据。
全局锁对于备份主从数据库存在的问题:

  • 备份主库则写操作相关的业务会全部阻塞。
  • 备份从库则备份期间无法执行主库同步来的数据,导致主从延迟。

在InnoDB中通过添加-single-transaction参数可以实现不加锁的一致性数据备份。(原理是快照,应该是MVCC的内容)

三、表级锁

表级锁分为三类,本质都是基于读写锁

  • 表锁 :对整张表加锁,解决DML之间的并发冲突
  • 元数据锁MDL :解决DML和DDL的并发冲突
  • 意向锁 :解决表锁和行锁的冲突

1.表锁

表锁又分为read lock和write lock两类。这里和缓存更新的读写锁原理一样。

  • 加锁:lock tables 表名... read/wirte;
  • 释放锁:unlock tables; 持有锁的线程断开连接会自动释放锁。

1.1 read lock

表共享读锁,又叫读锁,共享锁。执行读操作业务的线程申请读锁或不加锁 ,可以被多个读线程同时持有,持有锁的线程可以对该表进行读操作,但所有线程不能进行写操作

如果有多个线程都持有同一个表的读锁,那么只要还有一个线程持有读锁,写操作就会被阻塞,直到所有读线程都释放锁,因此写线程会有饥饿问题。

  • 在任何隔离级别下,select lock in share mode、update、delete、insert操作,共享锁和排它锁在事务提交时释放
  • 在serializable隔离级别下,普通的select操作会自动添加lock in share mode后缀。
  • 在读未提交、读已提交、可重复读隔离级别下,普通的select操作不会加锁

1.2 write lock

表独占写锁,又叫写锁,排它锁,独占锁。执行写操作业务的线程申请写锁,写锁只能由一个线程持有,期间其他线程的增删改查都会被阻塞,直到写线程释放锁。

2.元数据锁

元数据锁是为了防止DML和DDL冲突

MySQL会为执行增删查改操作的表自动加元数据共享锁 ,期间不允许表结构被修改,直到所有线程都不持有共享锁。当要alter table 修改表结构时会自动对表加元数据排它锁,期间不允许任何的增删查改操作。

3.意向锁

意向锁是为了解决行锁与表锁的冲突,加表锁前不必逐行遍历判断是否有行锁,直接判断意向锁即可。

读线程在加行锁时 会额外将意向锁设为 意向共享锁,写线程在加行锁时 会额外将意向锁设为 意向排它锁。

读线程加表锁前判断意向锁是共享锁,那么可以加表锁。意向锁为空时也可以加表锁。其他任何情况都不能加表锁。

四、行级锁

因为InnoDB中的数据存储结构是索引,所以行锁是对记录在索引B+树上的索引项加锁,而不是对记录加锁。

  • 行锁:锁定单个索引项 ,防止其他线程对该项进行update和delete,应用在读已提交、可重复读 事务隔离级别。

  • 间隙锁:锁定索引项之间的间隙 ,确保索引记录之间的间隙不变,防止其他线程在间隙进行insert,解决幻读 ,应用在可重复读 事务隔离级别。

  • 临键锁:同时锁定单个索引项和索引项前的间隙 ,应用在可重复读 事务隔离级别。

1.行锁

行锁实现还是读锁和写锁。在InnoDB中,对insert、update、delete加排它锁,对select不加锁。 其中,排它锁解决了脏读问题,MVCC解决了不可重复读和幻读问题。

2.临键锁

InnoDB在可重复读 事务隔离级别下使用的是临键锁防止幻读

  • SQL执行时若针对unique索引 的B+树进行搜索且是等值匹配 时会降级为行锁
  • SQL执行时若针对unique索引 的B+树进行搜索且是等值匹配 ,且索引项不存在 时会降级为间隙锁。例如索引项1,2,4,5,此时对索引项3进行增删改会先将2,4之间的间隙上锁。
  • SQL执行时若针对非unique索引 的B+树进行搜索且是等值匹配 ,且索引项不存在 时会降级为间隙锁。例如索引项1,2,2,4,5,此时对索引项3进行增删改会先将2,4之间的间隙上锁。
  • SQL执行时若不走任何索引,那么会升级为表锁。
相关推荐
小菜同学爱学习9 分钟前
第一章 初识达梦数据库:基础认知与环境准备
数据库·达梦
zhoutongsheng12 分钟前
如何解决ORA-01078参数文件错误_pfile与spfile互相创建恢复
jvm·数据库·python
m0_7162550014 分钟前
批处理一道例题+答案解析+批处理知识点总结 | 批处理高频易错场景 + 正确写法对照表
数据库·oracle
2401_8242226916 分钟前
HTML怎么标注字数限制提示_HTML实时字数统计占位【详解】
jvm·数据库·python
y = xⁿ19 分钟前
MySQL八股知识合集
android·mysql·adb
稀饭过霍31 分钟前
数据类型【TINYINT、SMALLINT、INT、BIGINT、decimal(18,2)】表示意思
数据库
俺不要写代码35 分钟前
数据库:DML
数据库·oracle
这个DBA有点耶37 分钟前
两张百万级大表JOIN跑崩了?试试这3招
数据库·代码规范
IntMainJhy43 分钟前
「Flutter三方库sqflite的鸿蒙化适配与实战指南:从入门到踩坑的本地数据库开发全记录」
数据库·flutter·华为·信息可视化·数据库开发·harmonyos
counting money1 小时前
Spring框架基础(依赖注入-全注解形式)
java·数据库·spring