MySQL 锁机制

优质博文:IT-BLOG-CN

定义:锁是计算机协调多个进程或线程并发访问某一资源的机制。

一、表锁(偏读)

MyISAM 引擎,开销小,加锁快,无死锁、锁定粒度大、发生锁冲突的粒度最高,并发度低。
【1】手动增加表锁:lock table 表名1 read(write),表名2 read(write),其他;
【2】查看那些表加锁:show open tables
【3】释放表:unlock tables,也可以在客户端断开的时候自动释放;

【结论】: 当 session1 对 my_lock 表加了 read 表锁后,①、不能对其它表进行操作。②、当 session 对 my_lock 进行写操作时,会挂起排队等待解锁。当 session1 对 my_lock 表加了 write 表锁后,①、当 session 读 my_lock 表时,会阻塞等待 session1 释放锁。

表锁主要是 MyISAM 引擎的特点,主要用于查询操作。MyISAM 在执行查询语句前,会自动给涉及到的所有表加读锁,在执行增删改之前,会给所有的表加写锁。

【如何分析表锁定】: 可以通过检查table_locks_waited table_locks_immediate状态来分析系统上的表锁定。

show status like 'table%';

 ■ table_locks_immediate:产生表级锁定的次数,表示可以立即获取锁的查询次数,每获取锁一次值加1;
 ■ table_locks_waited:出现表级锁定争用而发生等待的次数(不能立即获取锁);

二、行锁(偏写)

行锁就是针对数据表中行记录的锁。比如事务A更新了一行,而这时候事务B也要更新同一行,则必须等事务A的操作完成后才能进行更新。

行锁分为如下两种:
共享锁(Shared Locks): 简称S锁。在事务要读取一条记录时,需要先获取该记录的S锁;
独占锁(Exclusive Locks): 简称X锁。在事务要改动一条记录时,需要先获取该记录的X锁;

读取一条记录时需要获取一下该记录的S锁,其实这是不严谨的。如果只是普通的读,那么是不会加锁的。想要在读取记录时获取记录的锁有两种SELECT语句:
【1】对读取的记录加S锁:

SELECT ... LOCK IN SHARE MODE;

【2】对读取的记录加X锁:

SELECT ... FOR UPDATE;   

写操作所加的锁:
【1】DELETE: 对一条记录做 DELETE操作的过程其实是先在 B+树中定位到这条记录的位置,然后获取这条记录的X锁,然后再执行 delete mark操作。
【2】UPDATE: ① 如果未修改该记录的键值并且被更新的列占用的存储空间在修改前后未发生变化,则先在 B+树中定位到这条记录的位置,然后再获取记录的 X锁;② 如果未修改该记录的键值并且至少有一个被更新的列占用的存储空间在修改前后发生变化,则先在 B+树中定位到这条记录的位置,然后获取记录的 X锁,将该记录彻底删除掉(就是把记录彻底移入垃圾链表),最后再插入一条新记录。也就是会获取 X锁和隐式锁。③ 如果修改了该记录的键值,则相当于在原记录上做 DELETE操作之后再来一次 INSERT操作,加锁操作就需要按照 DELETE和 INSERT的规则进行了。
【3】INSERT: 通过一种称之为隐式锁来保护这条新插入的记录在本事务提交前不被别的事务访问。

如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

行锁偏向 InnoDB 引擎,开销大,加锁慢、会出现死锁、锁定粒度小、发生冲突的概率低,并发度高。

InnoDB 与 MyISAM 最大的不同是:①、一个支持事务,②、采用了行级锁。

【结论】: 当 session1 对一行数据修改,但未提交时,session2 修改行数据时会阻塞,但是可以查询,但查到的是旧数据。

取消自动提交:set autocommit=0;

【无索引行锁升级为表锁】: 当索引失效后,会导致此问题。
【间隙锁危害】: 当我们使用范围条件而不是相等条件检索数据,并请求共享锁或排它锁时,InnoDB 会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但不存在的记录,叫做 “间隙(GPA)”,InnoDB 也会对这个 “间隙” 加锁,这种锁机制就是所谓的“间隙锁”(Next-Key锁),解决幻读问题。
因为 Query 执行过程中通过范围进行查找,他会锁定整个范围内索引的索引键值,即使这个键值不存在。间隙锁有一个致命的弱点,就是当锁定一个范围之后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据,在某些场景下这可能会对性能造成很大的危害。
【如何加行锁】:

【行锁分析命令如下】:

show status like 'innodb_row_lock%';

 ■ Innodb_row_lock_current_waits:当前正在等待锁定的数量。
 ■ Innodb_row_lock_time:从系统启动到现在锁定总时间长度。
 ■ Innodb_row_lock_time_avg:每次等待所花的平均时间。
 ■ Innodb_row_lock_time_max:从系统启动到现在等待最长的一次时间。
 ■ Innodb_row_lock_waits:系统启动后到现在总共等待的次数。

三、隐试锁 Gap Lock以及 next-key lock

Gap Lock以及next-key lock是为了解决幻读的。产生幻读的原因是,行锁只能锁住行,但是新插入记录这个动作,要更新的是记录之间的“间隙”。因此,为了解决幻读问题,InnoDB只好引入新的锁,也就是间隙锁(Gap Lock)。间隙锁,锁的就是两个值之间的空隙。如下,表t,初始化插入了6个记录,这就产生了7个间隙。

 CREATE TABLE `t` (`id` int(11) NOT NULL,`c` int(11) DEFAULT NULL,`d` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `c` (`c`)) ENGINE=InnoDB;insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

当你执行 select * from t where d=5 for update的时候,就不止是给数据库中已有的6个记录加上了行锁,还同时加了7个间隙锁。这样就确保了无法再插入新的记录。间隙锁之间是不存在冲突的,例如:

SessionASessionB
begin;select * from t where c=7 lock in share mode;
begin;select * from t where c=7 for update;

这里 session B并不会被堵住。因为表t 里并没有 c=7这个记录,因此 session A加的是间隙锁(5,10)。而 sessionB 也是在这个间隙加的间隙锁。它们有共同的目标,即:保护这个间隙,不允许插入值。但它们之间是不冲突的。间隙锁和行锁合称 next-key lock, 每个 next-key lock是前开后闭区间。如果用 select * from t for update要把整个表所有记录锁起来,就形成了7个 next-key lock,分别是 (-∞,0]、(0,5]、(5,10]、(10,15]、(15,20]、(20, 25]、(25, +supremum]。

间隙锁造成的死锁: 我用两个 session来模拟并发,并假设往表里插入一条 id=9的数据。

MySQL

【1】session A 执行select … for update语句,由于id=9这一行并不存在,因此会加上间隙锁(5,10);
【2】session B 执行select … for update语句,同样会加上间隙锁(5,10),间隙锁之间不会冲突,因此这个语句可以执行成功;
【3】session B 试图插入一行(9,9,9),被session A的间隙锁挡住了,只好进入等待;
【4】session A试图插入一行(9,9,9),被session B的间隙锁挡住了;
间隙锁的引入,可能会导致同样的语句锁住更大的范围,这其实是影响了并发度的;

四、全表扫描

假如 country列上未建索引,所以只能采用全表扫描的方式来执行这条查询语句,扫描过的行会先加锁,然后再释放掉:

SELECT * FROM hero WHERE country  = '魏' LOCK IN SHARE MODE;

对于UPDATE …和DELETE …的语句来说,在遍历聚簇索引中的记录,都会为该聚簇索引记录加上X型行锁,然后:
【1】如果该聚簇索引记录不满足条件,直接把该记录上的锁释放掉;
【2】如果该聚簇索引记录满足条件,则会对相应的二级索引记录加上 X型行锁。

页锁:开销和加锁时间界于行表锁之间;会出现死锁;锁定粒度界于行表锁之间,并发度一般。(了解即可)

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

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

相关文章

【MySQL】对表的相关操作(DDL)

👦个人主页:Weraphael ✍🏻作者简介:目前学习计网、mysql和算法 ✈️专栏:MySQL学习 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论&#x1f4ac…

GPT-5可能会在今年夏天作为对ChatGPT的“实质性改进”而到来

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

MQ组件之RabbitMQ学习

MQ组件之RabbitMQ入门 同步调用和异步调用 在微服务架构中,服务之间的调用有同步调用和异步调用两种方式。 我们使用OpenFeign去调用是同步调用,同步调用的缺点很明显,在下图的场景中,支付完成后需要调用订单服务、仓库服务、短…

字符型数据详解

1 字符常量 C的字符常量是用单撇号括起来的一个字符。如a,x,D,?,$等都是字符常量。注意,a和A是不同的字符常量。 除了以上形式的字符常量外,C还允许用一种特殊形式的字符常量,就是以一个“\”开头的字符序列。例如,前面已经遇到过的,在printf函数中的…

DPDK and Trex环境指南

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、测试拓扑图 二、VirtualBox的网卡配置 三、DPDK支持的网卡 四、DPDK安装 1.DPDK向导 1). 英文向导 2). 中文向导 2.DPDK源码下载 3.DPDK源码解压 4.…

今日问题:动态分配内存出错

2024.3.22 在搜素了许多文章和查阅了许多博客后依然没有找到问题所在&#xff0c;最后无意之间翻看以前的关于动态内存管理的代码后发现&#xff1a; 没加头文件&#xff1a;#include<stdlib.h> 苦笑不得了属于是 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio…

蓝桥杯day7刷题日记

P8697 [蓝桥杯 2019 国 C] 最长子序列 思路&#xff1a;直接遍历&#xff0c;和子序列相同就记录&#xff0c;不然就下一位 #include <iostream> #include <string> using namespace std; int res;int main() {string s,t;cin>>s>>t;int i0,j0;while…

关于msvcp140.dll丢失的解决方法详情介绍,修复dll文件的安全注意事项

在使用电脑的过程中&#xff0c;是否有遇到过关于msvcp140.dll丢失的问题&#xff0c;遇到这样的问题你是怎么解决的&#xff0c;都有哪些msvcp140.dll丢失的解决方法是能够完美解决msvcp140.dll丢失问题的&#xff0c;今天小编将带大家去了解msvcp140.dll文件以及分析完美解决…

代码随想录 Day-23

力扣题目 406.根据身高重建队列 思路 这里可以看出来是有两个维度考虑&#xff0c;和力扣题目 135.分发糖果&#xff08;可以看我day-22的文章&#xff09; 有点类似。 因此遇到这种两个维度权衡的时候&#xff0c;一定是先考虑一个维度再按照另一个维度来重新考虑排序。 两…

innodb 的 buffer pool 管理 page

page 页结构 page是整个InnoDB存储的最基本构件&#xff0c;也是InnoDB磁盘管理的最小单位&#xff0c;与数据库相关的所有内容都存储在这种Page结构里。 Page分为几种类型&#xff0c;常见的页类型有 数据页(Btree Node)Undo页(Undo Log Page)系统页(System Page)事务数据页 …

PC显示字体和浏览器的字体不一致

1&#xff1a;设置了PC的区域&#xff0c;显示字符&#xff0c; 2&#xff1a;导致浏览器显示的字符一半大一半小 3&#xff1a;为什么去设置这个&#xff0c;因为担心封号 4&#xff1a;不让它检测出我是他大佬

【C++初阶】第七站:string类的初识(万字详解、细节拉满)

前言&#xff1a; &#x1f4cd;本文知识点&#xff1a;string的初识 &#x1f4a8;个人博客:Dream_Chaser&#xff5e;-CSDN博客 &#x1f6a9;本专栏&#xff1a;C 目录 一、什么是STL 二、STL的六大组件 三、STL的缺陷 四、为什么学习string类&#xff1f; 五、标准库中…

云ERP vs 本地ERP:优劣对比与选择指南

在性能方面&#xff0c;本地ERP需要需要较高级别的计算机系统和其他设备来确保其高效运行。如果企业的计算机设备不够先进&#xff0c;那么选择本地ERP可能导致系统性能下降。而云ERP解决方案则能保证性能&#xff0c;只要企业拥有稳定的互联网连接即可。 在成本方面&#xff0…

Linux的基本使用

1.Linux的背景 1.1什么Linux Linux是⼀个操作系统.和Windows是"并列"的关系. 1.2Linux系统的优势 1. 开源(意味着免费,便宜) 2. 稳定(Linux可以运⾏很多年,都不会发⽣重⼤问题) 3. 安全(Linux只有管理员或者特定⽤⼾才能访问Linux内核) 4. ⾃由(不会被强加商业产品和…

EasyCloud软件简介

运行环境&#xff1a;Win10 PCL1.9 VTK8.1 Qt5.12 VS2017 基于PCL点云库的三维点云数据处理软件 1&#xff0e;软件用户界面 本软件的用户界面主要包括以下几个部分&#xff08;如图1&#xff09;&#xff1a; [1]菜单栏&#xff0c;将软件功能模块划分为不同菜单&…

JAVA八股--集合面试题

AVA八股--集合面试题--上 java只有值传递&#xff0c;没有引用传递代理模式Java之HashMap和Hashtable选用 ArrayDeque 来实现队列要比 LinkedList 更好为什么HashMap的长度一定是2的次幂&#xff1f;HashMap常见遍历方式 java只有值传递&#xff0c;没有引用传递 文章讲解 文…

第四讲 Buffer Pool

问题&#xff1a;DBMS 是如何管理其内存和磁盘之间来回移动数据的&#xff1f; 答案&#xff1a;在决定如何在磁盘中来回移动数据时&#xff0c;我们必须考虑两个关键方面&#xff1a; 空间控制【Spatial Control】&#xff1a; 将页【pages】写在在磁盘的什么地方&#xff…

vsc ctrl+. 无效的问题

描述 ubuntu ibus 输入法 vsc ctrl.快捷键无效 输出 _e 解决方案: 运行 ibus-setup 把表情符号这里的快捷键改了

mysql 空间查询 多边形内的点

数据库查询 # 1新增空间point类型坐标字段 ALTER TABLE gaoxin_isdp.business_master ADD COLUMN location2 point NULL AFTER location;# 2从原字段更新点位字段&#xff0c;原字段poi1是字符串106.474596,29.464360 UPDATE business_master SET location POINT(substr(poi…

基于Springboot+Vue的前后端分离的简单Demo案例(一)

后端创建Springboot项目 创建数据库表结构及表信息 添加依赖&#xff08;pom.xml&#xff09; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/X…