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执行时若不走任何索引,那么会升级为表锁。
相关推荐
山峰哥2 小时前
SQL性能优化实战:从索引策略到查询优化案例全解析
大数据·数据库·sql·oracle·性能优化·架构
rannn_1112 小时前
【SQL题解】力扣高频 SQL 50题|DAY5
数据库·后端·sql·leetcode·题解
松涛和鸣2 小时前
DAY38 TCP Network Programming
linux·网络·数据库·网络协议·tcp/ip·算法
ss2732 小时前
ThreadPoolExecutor七大核心参数:从源码看线程池的设计
java·数据库·算法
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue健康茶饮销售管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
陌路202 小时前
redis的哨兵模式
数据库·redis·缓存
ohoy2 小时前
mysql数据存在则更新、不存在插入
数据库·mysql
TG:@yunlaoda360 云老大2 小时前
华为云国际站代理商TaurusDB的读写分离是如何实现的?
服务器·数据库·华为云