『 MySQL篇 』:MySQL 锁机制介绍

news2024/10/6 18:28:07

目录

一. 概述

二. 全局锁

三 . 表级锁

三. 行级锁


一. 概述

锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

MySQL中的锁按照锁的粒度分,分为一下三类:

  • 全局锁:锁定数据库中所有的表。
  • 表级锁:每次操作锁住整张表
  • 行级锁:每次操作锁住对应的行数据。

二. 全局锁

a. 介绍

全局锁就是对数据库的整个实例加锁, 加锁之后整个实例就处于只读状态,后续的DML写语句,DDL语句,以及更新操作的事务提交语句都会被阻塞,全局锁的典型使用场景就是进行全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

为什么进行全库备份时候加全局锁呢?

下面我们通过一个简单的例子来介绍一下不加全局锁时,可能出现的问题

假设数据库中存在着三张表 , tb_stock 库存表,tb_order 订单表,tb_orderlog 订单日志表。

在进行数据备份时 :

  • 先备份了 tb _ stock 表
  • 然后接下来, 在业务系统中,执行了下单操作,扣减库存, 生成订单,(更新 tb_stock 表, 插入 tb _ order 表)
  • 然后再执行备份 tb_order 表 的逻辑
  • 业务中执行插入订单日志的操作
  • 最后 , 备份了 tb_orderlog 表

再上述的执行过程中, 备份出来的数据是存在问题的 , 因为备份出来的数据 , tb_stock 表 和 tb_order 表 存在着数据不一致的问题, 有最新的订单信息 , 但是总的库存数没有发生变化

那如何规避这种数据不一致的现象呢 , 此时就需要借助 MySQL 的全局锁来解决:

此时 , 我们再来分析一下加了全局锁之后的情况:

在进行数据库的逻辑备份之前, 先对数据库加上全局锁,一旦加上全局锁之后,其他的DDL,DML全部都处于阻塞状态,

但是可以执行DQL语句,也就是只读状态,而数据备份就是查询操作, 那么在数据备份的过程中 , 数据库中的数据是不会发生变化的,这样就保证了数据的完整性和一致性.

b. 操作

  • 加全局锁
flush tables with read lock;
  • 数据备份
mysqldump -uroot –p1234 itcast > itcast.sql
  • 释放锁
unlock tables;

c. 特点

数据库中如果加全局锁 , 是一个粒度比较重的操作, 容易存在以下问题:

  • 如果在主库上进行备份,那么在备份期间都不能执行更新操作,业务基本就处于停摆
  • 如果在从库上进行备份,那么在备份期间,从库不能执行主库同步过来的二进制文件 ,就会导致主从延迟.

在 InnoDB 引擎中, 可以通过备份时增加一个参数来完成不加锁的数据一致性备份

mysqldump --single-transaction -uroot –p123456 itcast > itcast.sql

三 . 表级锁

表级锁 , 顾名思义,每次操作能够锁住整张表, 锁定粒度大,发生锁冲突概率较高,并发度最低 , 通常应用在 InnoDB , MyISAM, BDB 等引擎当中, 此处我们只对 InnoDB 中的表级锁进行详解:

1. 表锁

对于表级锁, 主要分为以下三类:

  1. 表锁
  2. 元数据锁
  3. 意向锁

对于表锁 , 主要分为两类

  1. 表共享读锁(read lock )

特点 : 对指定表加了读锁之后,当客户端一进行读操作时,不会影响客户端二的读,但是都会阻塞两哥客户端的写操作.

  1. 表独占写锁(write lock)

针对指定表增加了独占写锁之后, 客户端一可以针对表进行读和写, 而客户端二的读和写就会被阻塞

语法:

  • 加锁:lock tables 表名... read/write。
  • 释放锁:unlock tables / 客户端断开连接 。

总结: 读锁不会阻塞其他客户端的读 , 但是会阻塞写 , 写锁既会阻塞其他客户端的读,又会阻塞其他客户端的写。

2. 元数据锁

元数据锁,简写MDL。MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性

这里的元数据,大家可以简单理解为就是一张表的表结构。 也就是说,某一张表涉及到未提交的事务时,是不能够修改这张表的表结构的。

在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)。

那如果数据库有一个长事务(所谓的长事务,就是开启了事务,但是一直还没提交),那在对表结构做变更操作的时候,可能会发生意想不到的事情,比如下面这个顺序的场景:

  1. 首先,线程 A 先启用了事务(但是一直不提交),然后执行一条 select 语句,此时就先对该表加上 MDL 读锁;
  2. 然后,线程 B 也执行了同样的 select 语句,此时并不会阻塞,因为「读读」并不冲突;
  3. 接着,线程 C 修改了表字段,此时由于线程 A 的事务并没有提交,也就是 MDL 读锁还在占用着,这时线程 C 就无法申请到 MDL 写锁,就会被阻塞,
  4. 那么在线程 C 阻塞后,后续有对该表的 select 语句,就都会被阻塞,如果此时有大量该表的 select 语句的请求到来,就会有大量的线程被阻塞住,这时数据库的线程很快就会爆满了。

这是因为申请 MDL 锁的操作会形成一个队列,队列中写锁获取优先级高于读锁,一旦出现 MDL 写锁等待,会阻塞后续该表的所有 CRUD 操作。

共享锁:允许多个事务同时持有该锁,用于读取数据时,避免其他事务对数据进行修改。共享锁不会阻塞其他事务的共享锁请求,但会阻塞其他事务的独占锁和排他锁请求。

独占锁:只允许一个事务持有该锁,用于修改数据时,防止其他事务同时修改同一数据。独占锁会阻塞其他事务的共享锁和独占锁请求,但不会阻塞其他事务的排他锁请求。

排他锁:只允许一个事务持有该锁,用于修改数据时,防止其他事务同时修改同一数据。排他锁会阻塞所有其他事务的锁请求,包括共享锁、独占锁和排他锁。

MDL 是在事务提交后才会释放,这意味着事务执行期间,MDL 是一直持有的

  • 操作

查看元数据锁的加锁情况

mysql> select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
+-------------+--------------------+----------------+--------------+---------------+
| object_type | object_schema      | object_name    | lock_type    | lock_duration |
+-------------+--------------------+----------------+--------------+---------------+
| TABLE       | MySQL_Advanced     | tb_user        | SHARED_READ  | TRANSACTION   |
| TABLE       | MySQL_Advanced     | tb_user        | SHARED_READ  | TRANSACTION   |
| TABLE       | MySQL_Advanced     | tb_user        | SHARED_WRITE | TRANSACTION   |
| TABLE       | MySQL_Advanced     | user_logs      | SHARED_WRITE | TRANSACTION   |
| TABLE       | performance_schema | metadata_locks | SHARED_READ  | TRANSACTION   |
+-------------+--------------------+----------------+--------------+---------------+
5 rows in set (0.00 sec)

3. 意向锁

  1. 介绍

为了避免在DML进行执行时, 加的行锁与表锁相互冲突, 在 InnoDB 引擎中引入了意向锁, 使得表锁不需要去检查每行是否加锁 .

假如没有意向锁的情况下 , 客户端 一对表加了行锁之后, 客户端二如何给表进行加锁呢?

首先, 客户端一 , 开启一个事务, 然后执行 DML 操作, 在执行DML语句时, 会对涉及到的行进行加行锁.

当客户端二想要对这张表进行加表锁时,会检查当前表是否有对应的行锁,如果没有,则添加表锁,此时就会从第一行数据检查到最后一行 , 效率较低.

有了意向锁之后, 在执行DML操作时,会对涉及的行加上行锁,同时也会给该表加上意向锁.

而其他客户端对该表进行加表锁时,就可以根据是否存在意向锁来判断是否可以成功加锁.

  1. 分类
  • 意向共享锁 : 与表锁共享锁兼容, 与表锁排他锁互斥
  • 意向排他锁: 与表锁排他锁和表锁共享锁都互斥

意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)和独占表锁(lock tables ... write)发生冲突。

一旦事务提交了, 意向共享锁与意向排他锁都会释放

执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁 , 这样就可以快速判断表中是否有记录加锁.

三. 行级锁

每次操作锁住对应的行数据,锁定的粒度最小,发生锁冲突的概率最低,并发度最高,应用在InnoDB 引擎中

InnoDB 引擎与 MySlAM 引擎的三大区别:事务 外键 行锁

对于行级锁 , 主要分为以下三类:

  1. 行锁(Record Lock):锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC、RR隔离级别下都支持。

InnoDB中实现了以下两种类型的行锁:

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁
  • 排他锁(X):允许排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

两种行锁的兼容情况如下:

-- 会话 1
BEGIN;
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
-- 对 id=1 的数据行进行修改
UPDATE orders SET amount = amount + 100 WHERE id = 1;
COMMIT;

-- 会话 2
BEGIN;
-- 因为会话 1 对 id=1 的数据行进行了行锁,所以会话 2 不能同时对该行进行修改,
-- 如果执行下面的语句会一直等待会话 1 的事务提交或回滚
UPDATE orders SET amount = amount - 50 WHERE id = 1;
  1. 间隙锁

间隙锁:指对一个索引范围中的“空隙”进行锁定,防止其他事务在这个范围内插入新数据。间隙锁用于解决幻读问题。

例如在某个事务中执行了一个范围查询,然后在范围内的间隙处插入了新数据,这时再次执行相同的查询,会发现有一些行出现了两次,这就是幻读。通过间隙锁,可以防止其他事务插入新的数据,从而避免幻读。

假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。

-- 会话 1
BEGIN;
-- 对 id 大于 1 小于 10 的范围进行间隙锁定
SELECT * FROM orders WHERE id > 1 AND id < 10 FOR UPDATE;
-- 间隙锁会阻止其他事务在 id 大于 1 小于 10 的范围内插入数据,
-- 但允许其他事务在该范围之外的位置插入数据
COMMIT;

-- 会话 2
BEGIN;
-- 因为会话 1 对 id 大于 1 小于 10 的范围进行了间隙锁定,所以会话 2 不能在该范围内插入数据,
-- 如果执行下面的语句会一直等待会话 1 的事务提交或回滚
INSERT INTO orders (id, amount) VALUES (5, 500);
  1. 临键锁

临键锁与间隙锁的不同之处在于,他所锁定的不只是一个范围,还包括了锁定记录本身。

  • 索引上的等值查询(非唯一普通索引),向右遍历时最后一个值不满足查询需求时,临键锁退化为间隙锁。

假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。

所以,临键锁即能保护该记录,又能阻止其他事务将新纪录插入到被保护记录前面的间隙中。

临键锁之间的X,S锁之间的互斥关系同样遵循行锁之间的互斥关系。

  • 总结:

在 InnoDB 中,默认情况下是使用行锁实现事务隔离级别的。当需要锁定一整张表时,可以使用表锁;当需要解决幻读问题时,可以使用间隙锁。在使用间隙锁时,需要注意锁的范围,避免影响其他事务的正常操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/648549.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三菱FX5U通讯、定位、伺服32讲

三菱FX5U系列&#xff08;现在已经升级改成为MELSEC iQ-F系列&#xff09;PLC的CPU模块中内置了能够支持各种控制的优异功能&#xff0c;全系标配Ethernet端口、RS-485端口、SD存储卡槽。Ethernet端口可支持CC-Link IE现场网络Basic&#xff0c;因此能连接多种多样的设备。 第一…

eChart折线图动态特效和隔几秒高亮特效

示例&#xff1a; 说明&#xff1a; 因为现在公司经常要做大屏可视化特效&#xff0c;没办法&#xff0c;只能让图尽量动起来&#xff08;之前开会挨叼了&#xff0c;说俺们深圳做的&#xff0c;不能比西安那些人做的差。。。&#xff09; 主要代码&#xff1a; 折线图的滚呀滚…

基于Hexo和Butterfly创建个人技术博客,(7) 配置butterfly主题搭建博客网站主体UI框架

Butterfly官方网站&#xff0c;请 点击进入。 本文面向使用 butterfly theme 的用户, 主题安装方法可查看基于Hexo和Butterfly创建个人技术博客&#xff0c;(1) 初始化博客站点 这章内容。 一、概述 1、什么是theme? Hexo可以认为是一个基础框架&#xff0c;主要提供渲染和插…

平行云——开启通往元宇宙的通道

元宇宙是平行于真实世界的虚拟世界&#xff0c;是新一代互联网。具有真三维、可交互、可沉浸特性的XR&#xff0c;是构建元宇宙的终极数字媒体形态。如何打破XR终端设备与XR内容之间的紧耦合&#xff0c;实现任意平台、任意终端的线上访问&#xff0c;Cloud XR是其必由之路&…

Diffie-Hellman Key Agreement Protocol 资源管理错误漏洞(CVE-2002-20001)

详细描述: Diffie-Hellman Key Agreement Protocol是一种密钥协商协议。它最初在 Diffie 和 Hellman 关于公钥密码学的开创性论文中有所描述。该密钥协商协议允许 Alice 和 Bob 交换公钥值&#xff0c;并根据这些值和他们自己对应的私钥的知识&#xff0c;安全地计算共享密钥K…

C语言柔型数组

何为柔性数组 所谓柔性数组&#xff0c;是C语言中的一个概念&#xff0c;也叫零长数组。顾名思义&#xff0c;这个数组的长度是不固定的&#xff0c;当没有值时&#xff0c;它的sizeof长度为0。 我们一般这样定义一个柔性数组&#xff1a; struct buffer_t {int len;char buf…

FasterTransformer 002: cuda调试env

VSCODE ENV cmake NVIDIA Nsight Systems 当我们装好了CUDA的时候&#xff0c;其实在图形界面下已经装好了一个叫“nsight”的编译器&#xff0c;我们可以直接用终端打开这个编译器&#xff0c;然后写好程序直接编译然后debug就可以了。WINDOWS NVIDIA Nsight Systems 入门及…

【ARM AMBA APB 入门 1 -- APB总线介绍】

文章目录 APB 总线历史1.1 APB 总线介绍1.1.1 APB 使用场景1.1.2 APB 信号列表1.1.3 APB 状态机 1.2 APB 传输时序1.2.1 APB 写传输时序1.2.1.1 Write transfer with no wait states1.2.1.2 Write transfer with wait states 1.2.2 APB 读时序1.2.2.1 Read transfer with no wa…

C语言二级指针复习

之前写过一篇二级指针的博文&#xff0c;C语言二级指针Demo - Win32 版本_bcbobo21cn的博客-CSDN博客 下面复习一下二级指针&#xff1b; 二级指针的概念是这样&#xff0c; int a 100; int *p1 &a; int **p2 &p1; 有一个整型变量a被赋值100&#xff1b;…

【Python开发】FastAPI 10:SQL 数据库操作

在 FastAPI 中使用 SQL 数据库可以使用多个 ORM 工具&#xff0c;例如 SQLAlchemy、Tortoise ORM 等&#xff0c;类似 Java 的 Mybatis 。这些 ORM 工具可以帮助我们方便地与关系型数据库进行交互&#xff0c;如 MySQL 、PostgreSQL等。本篇文章将介绍如何使用 SQLAlchemy 来完…

osgb倾斜摄影三维模型数据web端在线管理平台,一键查看、分享

「四维轻云」是基于浏览器打造的一款osgb倾斜摄影三维模型数据web端在线管理平台&#xff0c;为用户提供了项目管理、团队管理、空间测量、场景编辑、在线标绘等功能&#xff0c;实现了osgb倾斜摄影三维模型数据在线管理、浏览和分享。 此外&#xff0c;为了更好地满足用户需求…

数据库信息速递 AWS因迁移PostgreSQL DBaaS而遭遇长时间停机时间而备受诟病

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

分享:win10使用 python 让 NVIDA GeForce MX250 显卡发挥余热,安装CUDA,cuDNN和PyTorch

目录 1. 更新最新的显卡驱动2. 安装CUDA3. 安装cuDNN4. 安装pytorch 1. 更新最新的显卡驱动 打开NVIDA更新驱动的官网地址 根据下图的选择&#xff0c;记得Windows驱动程序类型要选标准&#xff0c;如图 点击搜索&#xff0c;下面就会列出一大堆的历史驱动&#xff0c;选择第…

Stable Diffusion你需要知道的算法原理;ChatGPT新增函数调用;Adobe Illustrator引入AI工具Firefly;

&#x1f989; AI新闻 &#x1f680; OpenAI更新ChatGPT&#xff0c;新增函数调用、4倍上下文长度、更低的嵌入成本 摘要&#xff1a;OpenAI在官网发布了ChatGPT的更新细节&#xff0c;包括新增函数调用、GPT-4和GPT-3.5-Turbo的升级、降低成本等。其中&#xff0c;新增函数调…

接口使用https 为什么是一大段返回,而http是一行一行返回?

背景&#xff1a; 最近在调试chatgpt对话网站&#xff0c;因为返回数据比较大&#xff0c;就用到到了流读取。开始调用http一点都没有问题&#xff0c;但是上生产切换https时候始终抱错&#xff1f;这个问题纠结2天&#xff0c;终于在你chatgpt加持解决了 https 为什么是一大段…

Unity3D:场景视图视图选项

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 “场景视图视图选项”工具栏 您可以使用“场景视图视图选项”工具栏“叠加”来选择用于查看场景以及启用/禁用照明和音频的各种选项。这些控件仅在开发期间影响场景视图&#xff0…

mybatis二级缓存

MyBatis 缓存可以极大的提升查询效率。 MyBatis系统中默认定义两级缓存&#xff08;一级缓存和二级缓存&#xff09;。一、两级缓存 1、一级缓存&#xff1a;&#xff08;本地缓存&#xff09;&#xff1a;sqlSession级别的缓存。一级缓存是一直开启的&#xff1b;sqlSession级…

Kafka学习---4、消费者(分区消费、分区平衡策略、offset、漏消费和重复消费)

1、消费者 1.1 Kafka消费方式 1、pull&#xff08;拉&#xff09;模式&#xff1a;consumer采用从broker中主动拉取数据。 2、push&#xff08;推&#xff09;模式&#xff1a;Kafka没有采用这种方式。因为broker决定消息发生速率&#xff0c;很难适应所有消费者的消费速率。…

Hive的概念

Hive 概述 Hive是一个基于Hadoop的数据仓库系统&#xff0c;它提供了类似与SQL的查询语言HiveQL,可以将结构化数据存储在Hadoop分布式文件系统中&#xff0c;并通过MapReduce进行过处理。 Hive的目标是使数据分析师和其他人员能够使用SQL语言来查询大规模的数据集&#xff0…

Triton教程 --- Triton架构

Triton教程 —Triton架构 文章目录 Triton教程 ---Triton架构并发模型执行模型和调度器无状态模型状态模型控制输入隐式状态管理状态初始化调度策略直接的Oldest 合奏模型 下图显示了 Triton 推理服务器的高级架构。 模型存储库是一个基于文件系统的模型存储库&#xff0c;Trit…