SQL笔记 -- 锁

1. 概述

在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。为保证数据的一致性,需要对并发操作进行控制,因此产生了锁 。同时锁机制也为实现MySQL 的各个隔离级别提供了保证。 锁冲突也是影响数据库并发访问性能的一个重要因素。

2. 锁的不同角度分类

2.1 从数据操作的类型划分:读锁、写锁

  • 读锁 :也称为共享锁 、英文用 S 表示。针对同一份数据,多个事务的读操作可以同时进行而不会互相影响,相互不阻塞的。
  • 写锁:也称为排他锁 、英文用 X 表示。当前写操作没有完成前,它会阻断其他写锁和读锁。这样就能确保在给定的时间里,只有一个事务能执行写入,并防止其他用户读取正在写入的同一资源。

需要注意的是对于 InnoDB 引擎来说,读锁和写锁可以加在表上,也可以加在行上。

2.2 从数据操作的粒度划分:表级锁、页级锁、行锁

2.2.1 表锁
① 表级别的S锁、X锁

在对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,InnoDB存储引擎是不会为这个表添加表级别的S锁或者X锁的。在对某个表执行一些诸如ALTER TABLE 、 DROP TABLE这类的 DDL 语句时,其他事务对这个表并发执行诸如SELECT、INSERT、DELETE、UPDATE的语句会发生阻塞。同理,某个事务中对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,在其他会话中对这个表执行DDL语句也会发生阻塞。这个过程其实是通过在 server层使用一种称之为元数据锁(英文名: Metadata Locks , 简称 MDL )结构来实现的。

一般情况下,不会使用InnoDB存储引擎提供的表级别的S锁和X锁。只会在一些特殊情况下,比方说崩溃恢复过程中用到。比如,在系统变量 autocommit=0,innodb_table_locks = 1时, 手动获取 InnoDB存储引擎提供的表t 的S锁或者X锁可以这么写:

LOCK TABLES t READ` :InnoDB存储引擎会对表 t 加表级别的 `S锁 `。
LOCK TABLES t WRITE`InnoDB存储引擎会对表 t 加表级别的 `X锁` 
② 意向锁 (intention lock)

InnoDB 支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,而意向锁就是其中的一种表锁。

  1. 意向锁的存在是为了协调行锁和表锁的关系,支持多粒度(表锁和行锁)的锁并存。
  2. 意向锁是一种不与行级锁冲突的表级锁,这一点非常重要。
  3. 表明“某个事务正在某些行持有了锁或该事务准备去持有锁”

意向锁分为两种:

  • 意向共享锁(intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁)

    -- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
    SELECT column FROM table ... LOCK IN SHARE MODE;
    
  • 意向排他锁(intention exclusive lock, IX):事务有意向对表中的某些行加排他锁(X锁)

    -- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
    SELECT column FROM table ... FOR UPDATE;
    

即:意向锁是由存储引擎自己维护的 ,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前, InooDB 会先获取该数据行所在数据表的对应意向锁。

举例:

创建表teacher,插入6条数据,事务的隔离级别默认为Repeatable-Read,如下所示。

CREATE TABLE `teacher` (`id` int NOT NULL,`name` varchar(255) NOT NULL,PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;INSERT INTO `teacher` VALUES
('1', 'zhangsan'),
('2', 'lisi'),
('3', 'wangwu'),
('4', 'zhaoliu'),
('5', 'songhongkang'),
('6', 'leifengyang');
mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+

假设事务A获取了某一行的排他锁,并未提交,语句如下所示:

BEGIN;SELECT * FROM teacher WHERE id = 6 FOR UPDATE;

此时teacher表存在两把锁:teacher表上的意向排他锁与id为6的数据行上的排他锁。

事务B想要获取teacher表的表读锁,语句如下:

BEGIN;LOCK TABLES teacher READ;

此时事务B检测事务A持有teacher表的意向排他锁,就可以得知事务A必须持有该表中某些数据行的排他锁,那么事务B对teacher表的加锁请求就会被排斥(阻塞),而无需去检测表中的每一行数据是否存在排他锁。

意向锁的并发性

意向锁不会与行级的共享 / 排他锁互斥!正因为如此,意向锁并不会影响到多个事务对不同数据行加排他锁时的并发性。(不然我们直接用普通的表锁就行了)

事务A先获得了某一行的排他锁,并未提交:

BEGIN;SELECT * FROM teacher WHERE id = 6 FOR UPDATE;

事务A获取了teacher表上的意向排他锁。事务A获取了id为6的数据行上的排他锁。之后事务B想要获取teacher表上的共享锁。

BEGIN;LOCK TABLES teacher READ;

事务B检测到事务A持有teacher表的意向排他锁。事务B对teacher表的加锁请求被阻塞(排斥)。最后事务C也想获取teacher表中某一行的排他锁。

BEGIN;SELECT * FROM teacher WHERE id = 5 FOR UPDATE;

事务C申请teacher表的意向排他锁。事务C检测到事务A持有teacher表的意向排他锁。因为意向锁之间并不互斥,所以事务C获取到了teacher表的意向排他锁。因为id为5的数据行上不存在任何排他锁,最终事务C成功获取到了该数据行上的排他锁。

从上面的案例可以得到如下结论:

  1. InnoDB 支持多粒度锁,特定场景下,行级锁可以与表级锁共存。
  2. 意向锁之间互不排斥,但除了 IS 与 S 兼容外,意向锁会与共享锁 / 排他锁互斥 。
  3. IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。
  4. 意向锁在保证并发性的前提下,实现了行锁和表锁共存且满足事务隔离性的要求。
③ 元数据锁(MDL锁)

MySQL5.5引入了meta data lock,简称MDL锁,属于表锁范畴。MDL 的作用是,保证读写的正确性。比如,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个表结构做变更,增加了一 列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。

因此,当对一个表做增删改查操作的时候,加 MDL读锁;当要对表做结构变更操作的时候,加 MDL 写锁

读锁之间不互斥,因此你可以有多个线程同时对一张表增删查改。读写锁之间、写锁之间都是互斥的,用来保证变更表结构操作的安全性,解决了DML和DDL操作之间的一致性问题。不需要显式使用,在访问一个表的时候会被自动加上。

2.2.2 行锁

行锁(Row Lock)也称为记录锁,顾名思义,就是锁住某一行(某条记录 row)。需要注意的是,MySQL服务器层并没有实现行锁机制,行级锁只在存储引擎层实现

优点: 锁定力度小,发生锁冲突概率低,可以实现的并发度高。

缺点: 对于锁的开销比较大,加锁会比较慢,容易出现死锁情况。

InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。

① 记录锁(Record Locks)

记录锁也就是仅仅把一条记录锁,官方的类型名称为:LOCK_REC_NOT_GAP。比如我们把id值为8的那条记录加一个记录锁,仅仅是锁住了id值为8的记录,对周围的数据没有影响。

举例如下:

记录锁是有S锁和X锁之分的,称之为 S型记录锁和X型记录锁 。

  • 当一个事务获取了一条记录的S型记录锁后,其他事务也可以继续获取该记录的S型记录锁,但不可以继续获取X型记录锁;
  • 当一个事务获取了一条记录的X型记录锁后,其他事务既不可以继续获取该记录的S型记录锁,也不可以继续获取X型记录锁。
② 间隙锁(Gap Locks)

MySQL 在 REPEATABLE READ 隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用 MVCC 方 案解决,也可以采用加锁方案解决。但是在使用加锁方案解决时有个大问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些幻影记录加上记录锁。InnoDB提出了一种称之为 Gap Locks 的锁,官方的类型名称为: LOCK_GAP,我们可以简称为 gap锁 。

假如为id值为8的记录加了gap锁,意味着不允许别的事务在id值为8的记录前边的间隙插入新记录,假如id值为8的记录前是id为3的记录,那么其实就是 id列的值(3, 8)这个区间的新记录是不允许立即插入的。比如,有另外一个事务再想插入一条id值为4的新记录,它定位到该条新记录的下一条记录的id值为8,而这条记录上又有一个gap锁,所以就会阻塞插入操作,直到拥有这个gap锁的事务提交了之后,id列的值在区间(3, 8)中的新记录才可以被插入。

gap锁的提出仅仅是为了防止插入幻影记录而提出的。 虽然有共享gap锁和独占gap锁这样的说法,但是它们起到的作用是相同的。而且如果对一条记录加了gap锁(不论是共享gap锁还是独占gap锁),并不会限制其他事务对这条记录加记录锁或者继续加gap锁。

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

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

相关文章

继电器开关电路图大全

继电器是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路&#xff0…

vue-Mixin-复用代码片段

1. 介绍 在软件开发中,代码复用是一个重要的原则,它可以帮助我们避免重复的代码,提高代码的可维护性和可读性。在Vue.js中,我们可以使用mixins来复用代码片段。Mixin可以包含任何组件选项。当组件使用Mixin时,所有Mix…

Python笔记10-数据可视化练习折线图

文章目录 JSON数据Python数据和Json数据的相互转化pyecharts模块构建折线图全局配置绘制疫情数据折线图 JSON数据 JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据 。本质上是一个带有特定格式的字符串 主要功能:可以在各个编程语言中流通…

rust 各种骚操作

前言 rust 代码确实简介,但是各种操作做层出不穷,这里记录一下一些难以理解的晦涩语法。 正文 奇怪的省略值。 fn main() {let numbers (2, 4, 8, 16, 32);match numbers {(first, .., last) > {println!("Some numbers: {}, {}", fir…

零日漏洞:威胁与应对

一、引言 随着信息技术的迅猛发展,网络安全问题日益凸显。其中,零日漏洞已成为当今网络安全领域最受关注的问题之一。本文将深入探讨零日漏洞的威胁、产生原因以及应对策略,以期提高人们对这一问题的认识和防范意识。 二、零日漏洞的威胁 …

892. 台阶-Nim游戏

#include<bits/stdc.h>using namespace std;int main() {int n;cin>>n;int res0;for(int i1;i<n;i){int x;cin>>x;if(i%2){res^x;}}if(res) puts("Yes");else puts("No");return 0; }最优游戏策略是&#xff1a;如果另一个人操作的…

PostgreSQL 的对象层次

所有的数据库离开数据量来谈性能都是耍流氓。 就你那几万条的数据库&#xff0c;用啥都行&#xff0c;典型的就是怎么方便怎么来。 不过 PostgreSQL 上手确实比 MySQL 概念更多。 PostgreSQL 比 MySQL 多了一层。 PostgreSQL 是从PostgreSQL 是从 Database&#xff0c;到 S…

C++---string类

一.string类&#x1f357; C支持C风格的字符串&#xff0c;另外还提供了一种 字符串数据类型&#xff1a; string是定义在头文件string中的类&#xff0c;使用前需要包含头文件string。 #include<string> C语言中的字符串需要引用头文件#include<string.h> #includ…

RabbitMQ-业务的幂等性

一、幂等性处理方式 1、使用唯一id 生产者和消费者都需要添加配置类&#xff1a; Beanpublic MessageConverter jsonMessageConverter() {Jackson2JsonMessageConverter jackson2JsonMessageConverter new Jackson2JsonMessageConverter();jackson2JsonMessageConverter.set…

SpringMVC传递数据给前台

SpringMVC有三种方式将数据提供给前台 第一种 使用Request域 第二种 使用Model&#xff08;数据默认是存放在Request域中&#xff09; 与第一种方式其实是一致的 第三种 使用Map集合&#xff08;数据默认是存放在Request域中&#xff09;

20234.1.20 使用idea进行Java的helloworld程序开发

20234.1.20 使用idea进行Java的helloworld程序开发 idea毕竟是jtbrain的产品&#xff0c;整体和pycharm相同&#xff0c;初步使用感受比eclipse更亲切 一、程序结构 project&#xff08;项目&#xff0c;工程&#xff09; module&#xff08;模块&#xff09; package&…

回调地狱与解决方案

什么是回调地狱&#xff1f; 简单理解就是回调函数嵌套回调 示例&#xff1a; setTimeout(() > {console.log(1);setTimeout(() > {console.log(2);setTimeout(() > {console.log(3);}, 1000);}, 2000)}, 3000)如上代码所示&#xff0c;回调函数嵌套回调&#xff0c;就…

Django从入门到精通(一)

目录 一、Django环境搭建与命令 1.1、安装 1.2、命令行 创建项目 编写代码 运行 app概念 1.3、Pycharm创建项目 1.4、虚拟环境 创建虚拟环境 - 命令行 介绍 操作 基本问题 Pycharm 项目虚拟环境 django虚拟环境【安装django最新版本】 django虚拟环境【安装指…

L1-060 心理阴影面积(Java)

这是一幅心理阴影面积图。我们都以为自己可以匀速前进&#xff08;图中蓝色直线&#xff09;&#xff0c;而拖延症晚期的我们往往执行的是最后时刻的疯狂赶工&#xff08;图中的红色折线&#xff09;。由红、蓝线围出的面积&#xff0c;就是我们在做作业时的心理阴影面积。 现…

认识并使用Shiro技术

认识并使用Shiro 一、对Shiro的基本认知1、Shiro是什么&#xff1f;2、Shiro的核心组件是&#xff1f;2.1 Subject2.2 UsernamePasswordToken2.3 Realm&#xff08;重点是&#xff1a;AuthorizingRealm用于授权、AuthenticatingRealm用于认证&#xff09;2.4 SecurityManager2.…

OpenCV-Python(49):图像去噪

目标 学习使用非局部平均值去噪算法去除图像中的噪音学习函数cv2.fastNlMeansDenoising()、cv2.fastNlMeansDenoisingColored等 原理 在前面的章节中我们已经学习了很多图像平滑技术&#xff0c;比如高斯平滑、中值平滑等。当噪声比较小时&#xff0c;这些技术的效果都是很好…

基数(桶)排序

目录 基数排序 实现步骤 完整代码 基数排序 核心思想&#xff1a;统计原数组中某个元素在该数组中出现的次数 优点&#xff1a;效率极高&#xff0c;时间复杂度为O&#xff08;aN countN(范围)&#xff09; 缺点&#xff1a;不适合分散的数据&#xff0c;更适合集中数据…

ts中 any 和 unknown 有什么区别,分别什么时候使用

any 和 unknown 都是顶级类型 top type&#xff0c;也就是所有类型的父类型 &#xff08;1&#xff09;any代表任意类型&#xff0c; 是不做任何检查&#xff0c;相当于不使用 ts&#xff0c;不建议使用&#xff0c;使用 a as any as string 之类的&#xff0c;可以让类型检查…

[全连接神经网络]Transformer代餐,用MLP构建图像处理网络

一、MLP-Mixer 使用纯MLP处理图像信息&#xff0c;其原理类似vit&#xff0c;将图片进行分块(patch)后展平(fallten)&#xff0c;然后输入到MLP中。理论上MLP等价于1x1卷积&#xff0c;但实际上1x1卷积仅能结合通道信息而不能结合空间信息。根据结合的信息不同分为channel-mixi…

知识图谱KG+大模型LLM

LLM-based KG KnowLM OpenSPGKG-based RAG 基本原理 从query出发的语义解析 pre-LLM方法 思想&#xff1a;直接将问题解析为对应的逻辑表达式&#xff0c;然后到知识图谱中查询。 方法&#xff1a;通常包含逻辑表达式、语义解析算法、语义解析模型训练三部分。一般步骤是将问句…