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执行时若不走任何索引,那么会升级为表锁。
相关推荐
百结2142 小时前
Mysql数据库操作
数据库·mysql·oracle
keep one's resolveY3 小时前
时区问题解决
数据库
Leinwin3 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
qq_417695053 小时前
机器学习与人工智能
jvm·数据库·python
漫随流水3 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
ego.iblacat3 小时前
MySQL 服务基础
数据库·mysql
Maverick065 小时前
Oracle Redo 日志操作手册
数据库·oracle
攒了一袋星辰5 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql
W.D.小糊涂5 小时前
gpu服务器安装windows+ubuntu24.04双系统
c语言·开发语言·数据库
云贝教育-郑老师5 小时前
【OceanBase 的多租户架构是怎样的?有什么优势?】
数据库·oceanbase