MySQL学习Day28——锁

一、概述:

锁是计算机协调多个进程或线程并发访问某一资源的机制。在程序开发中会存在多线程同步的问题,当多个线程并发访问某个数据的时候,尤其是针对一些敏感的数据(比如订单、金额等)需要保证这个数据在任何时刻最多只有一个线程在访问,保证数据的完整性和一致性。在开发过程中加锁是为了保证数据的一致性,这个思想在数据库领域中同样很重要。

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

二、MySQL并发事务访问相同记录:

1.读-读情况:并发事务相继读取相同的记录,读取操作本身不会对记录有任何影响,并不会引起什么问题,所以允许这种情况的发生;

2.写-写情况:在这种情况下会发生脏写的问题,任何一种隔离级别都不允许这种问题的发生,所以在多个未提交事务相继对一条记录做改动时需要让它们排队执行,这个排队的过程其实是通过锁 来实现的。所谓的锁其实是一个内存中的结构,在事务执行前本来是没有锁的,也就是说一开始是没有锁结构和记录进行关联的,当一个事务想对这条记录做改动时,首先会看看内存中是否有与这条记录关联的锁结构,没有就会在内存中生成一个锁结构与之关联。如果有就会等待,当提交后便会释放掉它生成的锁结构;

不加锁:不需要在内存中生成对应的锁结构,可以直接进行操作;

加锁成功:在内存中生成了对应的锁结构,而且锁结构的is_waiting属性为false,也就是事务可以继续执行操作

加锁失败:在内存中生成了对应的锁结构,但是is_waiting属性为true,事务需要等待,不可以继续执行操作;

3.读—写或写—读情况:

读—写或写—读,即一个事务进行读取操作,另一个进行改动操作。这种情况下可能发生脏读、不可重复读、幻读的问题。各个数据库厂商对SQL标准的支持都可能不一样。比如MySQL在REPEATABLE READ隔离级别上就已经解决了幻读问题。

三、锁的不同角度分类:

1.从数据操作的类型划分:读锁和写锁

读锁:也称为共享锁,英文用S表示,针对同一份数据多个事务的读操作可以同时进行而不会相互影响,相互不阻塞的;

写锁:称为排它锁,英文用X表示,当前写操作没有完成前会阻断其他写锁和读锁,这样就能确保在给定的时间里只有一个事务能执行写入,防止其他用户读取正在写入的同一资源;

对于InnoDB引擎来说,读锁和写锁可以加在表上,也可以加在行上;

X锁S锁
X锁不兼容不兼容
S锁不兼容兼容

(1)锁定读:在采用加锁方式解决脏读 、 不可重复读 、 幻读这些问题时,读取一条记录时需要获取该记录的S锁其实是不严谨的,有时候需要在读取记录时就获取记录的X锁,来禁止别的事务读写该记录。对读取的记录加S锁格式如下:

SELECT ... LOCK IN SHARE MODE;
SELECT ... FOR SHARE;

在普通的SELECT语句后边加LOCK IN SHARE MODE,如果当前事务执行了该语句,那么它会为读取的记录加S锁,这样允许别的事务继续获取这些记录的S锁,但是不能获取这些记录的X锁,如果别的事务想要获取这些记录的X锁,那么它们会阻塞,直到当前事务提交之后将这些记录上的S锁释放掉。

对读取的记录加X锁:

SELECT ... FOR UPDATE;

在普通的SELECT语句后边加FOR UPDATE,如果当前事务执行了该语句,那么它会为读取的记录加X锁,这样既不允许别的事务获取这些记录的S锁,也不允许获取这些记录的X锁,如果别的事务想要获取这些记录的S锁或者X锁,那么它们会阻塞直到当前事务提交之后将这些记录上的X锁释放掉。

(2)写操作:

A.DELETE:

对一条记录做DELETE操作的过程其实是先在B+树中定位到这条记录的位置,然后获取这条记录的X锁,再执行delete mark操作。可以把这个定位待删除记录在B+树中位置的过程看成是一个获取X锁的锁定读。

B.UPDATE:

情况一:未修改该记录的键值,并且被更新的列占用的存储空间在修改前后未发生变化。则先在B+ 树中定位到这条记录的位置,然后再获取一下记录的X锁,最后在原记录的位置进行修改操作。可以把这个定位待修改记录在B+树中位置的过程看成是一个获取X锁的锁定读。

情况二:未修改该记录的键值,并且至少有一个被更新的列占用的存储空间在修改前后发生变化。则先在 B+ 树中定位到这条记录的位置,然后获取一下记录的X锁,将该记录彻底删除掉(就是把记录彻底移入垃圾链表),最后再插入一条新记录。这个定位待修改记录在B+树中位置的过程看成是一个获取X锁的锁定读 ,新插入的记录由INSERT操作提供的隐式锁进行保护。

情况三:修改了该记录的键值,则相当于在原记录上做DELETE操作之后再来一次INSERT操作,加锁操作就需要按照DELETE和INSERT的规则进行了。

C.INSERT:

一般情况下,新插入一条记录的操作并不加锁,通过一种称之为隐式锁的结构来保护这条新插入的记录在本事务提交前不被别的事务访问。

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

1.表锁(Table Lock):

表锁会锁定整张表,它是MySQL中最基本的锁策略,并不依赖于存储引擎(不管是MySQL的什么存储引擎对于表锁的策略都是一样的),并且表锁是开销最小的策略(因为粒度比较大)。由于表级锁一次会将整个表锁定,所以可以很好的避免死锁问题,当然锁的粒度大所带来最大的负面影响就是出现锁资源争用的概率也会最高,导致并发率大打折扣。

(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锁。只会在一些特殊情况下比方说崩溃恢复过程中用到:

LOCK TABLES t READ : InnoDB存储引擎会对表t加表级别的S锁;
LOCK TABLES t WRITE: InnoDB存储引擎会对表t加表级别的X锁;
锁类型自己可读自己可写自己可操作其他表他人可读他人可写
读锁
写锁

MyISAM在执行查询语句前,会给涉及的表加读锁,在执行增删改操作前会给涉及的表加写锁,InnoDB存储引擎不会为表添加表级别的读锁或者写锁.

(2)意向锁(intention lock):

InnoDB支持多粒度锁,允许行级锁和表级锁共存,意向锁就是其中的一种表锁;如果给某一行数据加上排它锁,数据库会自动给更大一级的空间加上意向锁,告诉其他人这个数据页或数据表已经有人上过排它锁,这样当其他人想要获取数据表排它锁的时候只需要了解是否有人已经获取了这个数据表的意向排他锁即可。

a.意向锁的存在是为了协调行级锁和表锁的关系、支持多粒度的锁并存;

b.意向锁是一种不与行级锁冲突的表级锁

c.表明某个事务正在某些持有了锁或者该事务准备去持有锁

d.如果事务想要获得数据表中某些记录的共享锁,就需要在数据表上添加意向共享锁

SELECT column FROM table_name ... LOCK IN SHARE MODE;

e.如果事务想要获得数据表中某些记录的排他锁,就需要在数据表上添加意向排他锁

SELECT column FROM table_name ... FOR UPDATE;
意向共享锁(IS)意向排他锁(IX)
意向共享锁(IS)兼容兼容
意向排他锁(IX)兼容兼容
意向共享锁(IS)意向排他锁(IX)
共享锁(S)兼容互斥
排他锁(X)互斥互斥

f.InnoDB支持多粒度锁,特定场景下行级锁可以与表级锁共存

g.意向锁之间互补排斥,但除了IS与S兼容外,意向锁会与共享锁和排它锁互斥

h.IX、IS是表级锁,不会和行级的X、S锁发生冲突,只会和表级的X、S发生冲突

i.意向锁在保证并发性的前提下实现了行级锁和表级锁共存且满足事务隔离性的要求

(3)自增锁(AUTO-INC锁)

插入数据的三种方式:

Simple inserts:简单插入,预先确定要插入的行数,包括没有嵌套子查询的单行和多行INSERT ... VALUES()和REPLACE语句;

Bulk inserts:批量插入,事先不知道要插入的行数,包括INSERT ... SELECT,REPLACE ... SELECT和LOAD DATA语句;

Mixed-mode inserts:混合模式插入,是Simple inserts语句但是指定部分新行的自动递增值;

AUTO-INC锁是当向使用含有AUTO_INCREMENT列的表中插入数据时需要获取的一种特殊的表级锁,在执行插入语句时就在表级别加一个AUTO-INC锁,然后为每条待插入记录的AUTO_INCREMENT修饰的列分配递增的值,在该语句执行结束后,再把AUTO-INC锁释放掉。一个事务在持有AUTO-INC锁的过程中,其他事务的插入语句都要被阻塞,可以保证一个语句中分配的递增值是连续的。

innodb_autoinc_lock_mode有三种取值,分别对应不同的锁定模式:

innodb_autoinc_lock_mode = 0(“传统”锁定模式):在此锁定模式下,所有类型的insert语句都会获得一个特殊的表级AUTO-INC锁,用于插入具有AUTO_INCREMENT列的表。使得语句中生成的auto_increment为顺序,且在bin log中重放的时候可以保证master与slave中数据的auto_increment是相同的。因为是表级锁,当在同一时间多个事务中执行insert的时候,对于AUTO-INC锁的争夺会限制并发能力。

innodb_autoinc_lock_mode =1(“连续“锁定模式):在这个模式下,“bulk inserts”仍然使用AUTO.INC表级锁,并保持到语句结束。对于“simple inserts”(要插入的行数事先已知),则通过在 mutex(轻量锁)的控制下获得所需数量的自动递增值来避免表级AUT0-INC锁,它只在分配过程的持续时间内保持,而不是直到语句完成,不使用表级AUTO-INC锁,除非AUTO-INC锁由另一个事务保持。如果另一个事务保持AUTO-INC锁,则"simple inserts"等待AUTO-INC锁如同它是一个“bulk inserts”。

innodb_autoinc_lock_mode = 2("交错"锁定模式):在这种锁定模式下,所有类INSERT语句都不会使用表级AUTO-INC锁,并且可以同时执行多个语句。这是最快和最可扩展的锁定模式,但是当使用基于语句的复制或恢复方案时,从二进制日志重播SQL语句时,这是不安全的。在此锁定模式下,自动递增值保证在所有并发执行的所有类型的insert语句中是唯一且单调递增的。但是由于多个语句可以同时生成数字(即跨语句交叉编号),为任何给定语句插入的行生成的值可能不是连续的。

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

2.InnoDB中的行锁:

行锁(Row Lock)也称为记录锁,顾名思义就是锁住某一行(某条记录row)。需要的注意的是MySQL服务器层并没有实现行锁机制,行级锁只在存储引擎层实现。行锁的锁定粒度小,发生锁冲突概率低,可以实现的并发度高。但是对于锁的开销比较大,加锁会比较慢,容易出现死锁情况。

(1)记录锁(Record Locks):记录锁就是仅仅把一条记录锁上。记录锁是有S锁和X锁之分的,当一个事务获取了一条记录的S型记录锁后,其他事务也可以继续获取该记录的S型记录锁,但不可以继续获取X型记录锁;当一个事务获取了一条记录的X型记录锁后,其他事务既不可以继续获取该记录的S型记录锁,也不可以继续获取X型记录锁。

(2)间隙锁(Gap Locks):gap锁的提出仅仅是为了防止插入幻影记录而提出的,如果对一条记录加了gap锁(不论是共享gap锁还是独占gap锁)并不会限制其他事务对这条记录加记录锁或者继续加gap锁。

(3)临键锁(Next-Key Locks):next-key锁的本质就是一个记录锁和一个gap锁的合体,既能保护该条记录,又能阻止别的事务将新记录插入被保护记录的前边的间隙

(4)插入意向锁(Insert Intention Locks):插入意向锁是在插入一条记录行前由INSERT操作产生的一种间隙锁。该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时事务之间不需要互相等待。插入意向锁是一种gap锁,不是意向锁,在insert操作时产生;插入意向锁是一种特殊的间隙锁,并且插入意向锁之间互不排斥,即使多个事务在同一取件插入多条记录,只要记录本身不冲突,事物之间就不会出现冲突等待;

3.页锁:页锁就是在页的粒度上进行锁定,锁定的数据资源比行锁要多,因为一个页中可以有多个行记录。当使用页锁的时候会出现数据浪费的现象,但这样的浪费最多也就是一个页上的数据行。页锁的开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。

五、从对待锁的态度划分:乐观锁、悲观锁

1.悲观锁(Pessimistic Locking):悲观锁是一种思想,顾名思义就是很悲观,对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性。悲观锁总是假设最坏的情况,每次去拿数据的时候都认为会修改,所以每次在拿数据的时候都会上锁,这样想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。

2.乐观锁(Optimistic Locking):乐观锁认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,也就是不采用数据库自身的锁机制,而是通过程序来实现。在程序上可以采用版本号机制或者CAS机制 实现,乐观锁适用于多读的应用类型,这样可以提高吞吐量。

3.使用场景:

(1)乐观锁适合读操作多的场景,相对来说写的操作比较少。它的优点在于程序实现,不存在死锁问题,不过适用场景也会相对乐观,因为它阻止不了除了程序以外的数据库操作。

(2)悲观锁适合写操作多的场景,因为写的操作具有排它性。采用悲观锁的方式可以在数据库层面阻止其他事务对该数据的操作权限,防止读-写和写-写的冲突。

六、按照加锁的方式划分:显式锁、隐式锁​​​​​​​

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯简单题,公司名称

题目链接&#xff08;需要登录&#xff09; #include <iostream> #include <cstring> #include <algorithm> using namespace std; bool lanqiao(string str,int len){ sort(str.begin(),str.end());//对str按照ascii排序if(str.find("Laainoq")s…

HTML静态网页成品作业(HTML+CSS)——安徽宣笔设计制作(5个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有6个页面。 &#x1f3f7;️想要…

Linux系统——web服务拓展练习

目录 一、实验环境搭建 1. Centos 7-5——Client 2. Centos 7-1——网关服务器 3. Centos 7-2——Web1 4. Centos 7-3——Web2 5. Centos 7-4——Nginx 二、在Nginx服务器上搭建LNMP服务&#xff0c;并且能够对外提供Discuz论坛服务&#xff1b;在Web1、Web2服务器上搭建…

springboot255基于spring boot的疫情信息管理系统

疫情信息管理系统的设计与实现 摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日常生活越来越离不开计算机和互联网技术。首先&#xff0c;根据收集到的用户需求分析&#xff0c;对设计系统有一个初步的认识与了解&#xff0c;确定疫情信息管理系统…

Unity Shader实现UI流光效果

效果&#xff1a; shader Shader "UI/Unlit/Flowlight" {Properties{[PerRendererData] _MainTex("Sprite Texture", 2D) "white" {}_Color("Tint", Color) (1, 1, 1, 1)[MaterialToggle] PixelSnap("Pixel snap", float…

【数据分享】2000-2022年全国1km分辨率的逐日PM10栅格数据

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2022年全国范围逐日的PM2.5栅格数据和2013-2022年全国范围逐日SO2栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;。 本次我们给大家带来的是2000-2022年全国范围的逐日的PM10栅…

吴恩达deeplearning.ai:倾斜数据集的误差指标精确率、召回率

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 文章目录 倾斜数据集的误差指标罕见病预测精确率和召回率 精确率和召回率的权衡精确率和召回率的矛盾关系 F1算法 倾斜数据集的误差指标 在神经网络中&#xff0c;如果你的数据集中正例和负…

giffgaff怎么充值?giffgaff怎么续费?

-性价比高&#xff1a;0月租&#xff0c;免费接收短信&#xff0c;充值一次&#xff0c;接码可以用20年以上&#xff08;仅需半年保号一次&#xff09;&#xff0c;可能是国内性价比最高的接码实体卡&#xff01;-安全&#xff1a;实体卡无须担心因号码被风控&#xff0c;还可以…

C语言:通讯录

目录 前言 1、通讯录框架&#xff0c;基本介绍 2、程序实现&#xff0c;步骤解释 2.1. 建立菜单 2.2. 主函数框架 2.3 前期工作 2.4 初始化通讯录函数&#xff1a;void InitContact(Contact* pc); 2.5 添加信息操作&#xff1a;void AddContact(Contact* pc); 2.6 显示…

Sublime Text 格式化Json文件 之 Pretty Json

需要使用到 Pretty Json插件。 一、安装方法 sublime 下&#xff0c;按快捷键 Comand control p&#xff0c; 输入install Package,然后回车 等几秒钟&#xff0c;加载启动进程完毕后弹出的页面中输入pretty json, 然后回车 等待几秒钟&#xff0c;可以查看Sublime 最下面的…

nginx配置支持ipv6访问,ipv4改造ipv6

一、前言 本地测试nginx部署的web系统支持ipv6地址访问。 二、本机ipv6地址 cmd ipconfig 找到IPv6地址 其中带有%号其实是临时分配得到地址 我们可以ping一下看看 另一种ping的方式 加上中括号 还有就是去掉%号 三、nginx增加配置 server块里增加 listen [::]:80; 四、测…

【SQL】指定日期的产品价格(IFNULL函数)

题目描述 leetcode题目&#xff1a;指定日期的产品价格 思路 找出所有的产品的指定的日期的价格&#xff1b;若找不到某个产品的更改日期&#xff0c;则将该产品价格设置为10。 关键点&#xff1a; if没有16号的&#xff0c;怎么找到前一个日期的&#xff1f;> 日期小…

【数字人】12、DINet | 使用形变+修复模块实现高清 talking head 生成(AAAI2023)

文章目录 一、背景二、方法2.1 deformation part2.2 inpainting part2.3 Loss 函数 三、效果3.1 数据集3.2 实现细节3.3 可视化效果 论文&#xff1a;DINet: Deformation Inpainting Network for Realistic Face Visually Dubbing on High Resolution Video 代码&#xff1a;h…

Yolov8-pose关键点检测:原创自研涨点系列篇 | 空间上下文感知模块(SCAM)结合超轻量高效动态上采样DySample

💡💡💡本文独家改进:YOLOV8-pose head创新,1)一种超轻量高效动态上采样DySample, 具有更少的参数、FLOPs,效果秒杀CAFFE和YOLOv8网络中的nn.Upsample;2)加入空间上下文感知模块(SCAM)进一步提升检测精度; 改进结构图如下: Yolov8-Pose关键点检测专栏介绍:ht…

回溯算法09-子集II(Java/子集问题的去重方法)

9.子集II 题目描述 给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列。 示例 1&#xff1a; 输入&#xf…

VMware虚拟机安装Ubuntu kylin22.04系统教程(附截图详细步骤)

一、版本信息 虚拟机产品&#xff1a;VMware Workstation 17 Pro 虚拟机版本&#xff1a;17.0.0 build-20800274 ISO映像文件&#xff1a;ubuntukylin-22.04-pro-amd64.iso 二、安装步骤 打开虚拟机&#xff0c;点击创建新的虚拟机&#xff1a; 选择自定义&#xff1a; 硬…

2024年新手视频剪辑软件推荐-6款视频剪辑软件测评

视频剪辑软件推荐 premiere premiere 直达地址:各大软件网站 说到底,还是得专业的来,虽然很多人觉得他是收费的,但是你懂的,想要免费总是会有办法的.别的不说,剪辑这块,我还是很认可这个软件,虽然我现在还是刚入门. 剪映 剪映 抖音官方推出的一款手机视频编辑剪辑应用,提供切割…

Full GC的认识、预防和定位

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ &#x1f440;&#x1f440;&#x1f440; 个人博客&#xff1a;小奥的博客 &#x1f44d;&#x1f44d;&#x1f44d;&#xff1a;个人CSDN ⭐️⭐️⭐️&#xff1a;传送门 &#x1f379; 本人24应届生一枚&#xff0c;技术和水平有限&am…

ChatGPT 串接到 Discord - 团队协作好助理

ChatGPT 串接到 Discord - 团队协作好助理 ChatGPT 是由 OpenAI 开发的一个强大的语言模型&#xff0c;本篇文章教你如何串接 Discord Bot &#xff0c;协助团队在工作上更加高效并促进沟通与协作。使 ChatGPT 发挥出最大的功效&#xff0c;进一步提升工作效率和团队协作能力。…

【已解决】无法删除自己上传在CSDN的资源怎么办?(2024亲测可用)

文章目录 1. 前情提要2. 实测过程3. 解决方案 1. 前情提要 我在 CSDN 上发布了一个免费资源&#xff0c;近几天却有粉丝反馈这个免费资源现在要开 VIP 才能下载&#xff0c;于是我想删除这个资源重新上传&#xff0c;但系统提示我没有权限&#xff0c;被下载过的资源无法删除&…