16、Mysql高级之锁问题

news2025/4/28 14:53:50

16、Mysql高级之锁问题

文章目录

  • 16、Mysql高级之锁问题
  • 1、锁概述
  • 2、锁分类
  • 3、Mysql 锁
  • 4、MyISAM 表锁
    • 4.1 如何加表锁
    • 5.2.2 读锁案例
    • 4.3、写锁案例
    • 4.4、结论
    • 4.5、查看锁的争用情况
  • 5、InnoDB 行锁
    • 5.1、行锁介绍
    • 5.2、背景知识
    • 5.3、InnoDB 的行锁模式
    • 5.4、案例准备工作
    • 5.5、行锁基本演示
    • 5.6、无索引行锁升级为表锁
    • 5.7、间隙锁危害
    • 5.8、InnoDB 行锁争用情况
    • 5.9、总结

1、锁概述

锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。

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

2、锁分类

从对数据操作的粒度分 :

1) 表锁:操作时,会锁定整个表。

2) 行锁:操作时,会锁定当前操作行。

从对数据操作的类型分:

1) 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。

2) 写锁(排它锁):当前操作没有完成之前,它会阻断其他写锁和读锁。

3、Mysql 锁

相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。下表中罗列出了各存储引擎对锁的支持情况:

存储引擎表级锁行级锁页面锁
MyISAM支持不支持不支持
InnoDB支持支持不支持
MEMORY支持不支持不支持
BDB支持不支持支持

MySQL这3种锁的特性可大致归纳如下 :

锁类型特点
表级锁偏向MyISAM 存储引擎,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

从上述特点可见,很难笼统地说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!仅从锁的角度来说:表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web 应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并查询的应用,如一些在线事务处理(OLTP)系统。

4、MyISAM 表锁

MyISAM 存储引擎只支持表锁,这也是MySQL开始几个版本中唯一支持的锁类型。

4.1 如何加表锁

MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT 等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用 LOCK TABLE 命令给 MyISAM 表显式加锁。

显示加表锁语法:

加读锁 : lock table table_name read;

加写锁 : lock table table_name write;

5.2.2 读锁案例

准备环境

create database demo_03 default charset=utf8mb4;

use demo_03;

CREATE TABLE `tb_book` (
  `id` INT(11) auto_increment,
  `name` VARCHAR(50) DEFAULT NULL,
  `publish_time` DATE DEFAULT NULL,
  `status` CHAR(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=myisam DEFAULT CHARSET=utf8 ;

INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'java编程思想','2088-08-01','1');
INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'solr编程思想','2088-08-08','0');



CREATE TABLE `tb_user` (
  `id` INT(11) auto_increment,
  `name` VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=myisam DEFAULT CHARSET=utf8 ;

INSERT INTO tb_user (id, name) VALUES(NULL,'令狐冲');
INSERT INTO tb_user (id, name) VALUES(NULL,'田伯光');

客户端 一 :

1)获得tb_book 表的读锁

lock table tb_book read;

2) 执行查询操作

select * from tb_book;

在这里插入图片描述

可以正常执行 , 查询出数据。

客户端 二 :

3) 执行查询操作

select * from tb_book;

在这里插入图片描述

客户端 一 :

4)查询未锁定的表

select name from tb_seller;

在这里插入图片描述

客户端 二 :

5)查询未锁定的表

select name from tb_seller;

在这里插入图片描述

可以正常查询出未锁定的表;

客户端 一 :

6) 执行插入操作

insert into tb_book values(null,'Mysql高级','2088-01-01','1');

在这里插入图片描述

执行插入, 直接报错 , 由于当前tb_book 获得的是 读锁, 不能执行更新操作。

客户端 二 :

7) 执行插入操作

insert into tb_book values(null,'Mysql高级','2088-01-01','1');

在这里插入图片描述

当在客户端一中释放锁指令 unlock tables 后 , 客户端二中的 inesrt 语句 , 立即执行 ;

4.3、写锁案例

客户端 一 :

1)获得tb_book 表的写锁

lock table tb_book write ;

2)执行查询操作

select * from tb_book ;

在这里插入图片描述

查询操作执行成功;

3)执行更新操作

update tb_book set name = 'java编程思想(第二版)' where id = 1;

在这里插入图片描述

更新操作执行成功 ;

客户端 二 :

4)执行查询操作

select * from tb_book ;

在这里插入图片描述

当在客户端一中释放锁指令 unlock tables 后 , 客户端二中的 select 语句 , 立即执行 ;

在这里插入图片描述

4.4、结论

锁模式的相互兼容性如表中所示:

在这里插入图片描述

由上表可见:

​ 1) 对MyISAM 表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;

​ 2) 对MyISAM 表的写操作,则会阻塞其他用户对同一表的读和写操作;

​ 简而言之,就是读锁会阻塞写,但是不会阻塞读。而写锁,则既会阻塞读,又会阻塞写。

此外,MyISAM 的读写锁调度是写优先,这也是MyISAM不适合做写为主的表的存储引擎的原因。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。

4.5、查看锁的争用情况

show open tables;

在这里插入图片描述

In_user : 表当前被查询使用的次数。如果该数为零,则表是打开的,但是当前没有被使用。

Name_locked:表名称是否被锁定。名称锁定用于取消表或对表进行重命名等操作。

show status like 'Table_locks%';

在这里插入图片描述

Table_locks_immediate : 指的是能够立即获得表级锁的次数,每立即获取锁,值加1。

Table_locks_waited : 指的是不能立即获取表级锁而需要等待的次数,每等待一次,该值加1,此值高说明存在着较为严重的表级锁争用情况。

5、InnoDB 行锁

5.1、行锁介绍

行锁特点 :偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

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

5.2、背景知识

事务及其ACID属性

事务是由一组SQL语句组成的逻辑处理单元。

事务具有以下4个特性,简称为事务ACID属性。

ACID属性含义
原子性(Atomicity)事务是一个原子操作单元,其对数据的修改,要么全部成功,要么全部失败。
一致性(Consistent)在事务开始和完成时,数据都必须保持一致状态。
隔离性(Isolation)数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的 “独立” 环境下运行。
持久性(Durable)事务完成之后,对于数据的修改是永久的。

并发事务处理带来的问题

问题含义
丢失更新(Lost Update)当两个或多个事务选择同一行,最初的事务修改的值,会被后面的事务修改的值覆盖。
脏读(Dirty Reads)当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
不可重复读(Non-Repeatable Reads)一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现和以前读出的数据不一致。
幻读(Phantom Reads)一个事务按照相同的查询条件重新读取以前查询过的数据,却发现其他事务插入了满足其查询条件的新数据。

事务隔离级别

为了解决上述提到的事务并发问题,数据库提供一定的事务隔离机制来解决这个问题。数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使用事务在一定程度上“串行化” 进行,这显然与“并发” 是矛盾的。

数据库的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏写、脏读、不可重复读、幻读这几类问题。

隔离级别丢失更新脏读不可重复读幻读
Read uncommitted×
Read committed××
Repeatable read(默认)×××
Serializable××××

备注 : √ 代表可能出现 , × 代表不会出现 。

Mysql 的数据库的默认隔离级别为 Repeatable read , 查看方式:

show variables like 'tx_isolation';

在这里插入图片描述

5.3、InnoDB 的行锁模式

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

  • 共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
  • 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);

对于普通SELECT语句,InnoDB不会加任何锁;

可以通过以下语句显示给记录集加共享锁或排他锁 。

共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE

5.4、案例准备工作

create table test_innodb_lock(
	id int(11),
	name varchar(16),
	sex varchar(1)
)engine = innodb default charset=utf8;

insert into test_innodb_lock values(1,'100','1');
insert into test_innodb_lock values(3,'3','1');
insert into test_innodb_lock values(4,'400','0');
insert into test_innodb_lock values(5,'500','1');
insert into test_innodb_lock values(6,'600','0');
insert into test_innodb_lock values(7,'700','0');
insert into test_innodb_lock values(8,'800','1');
insert into test_innodb_lock values(9,'900','1');
insert into test_innodb_lock values(1,'200','0');

create index idx_test_innodb_lock_id on test_innodb_lock(id);
create index idx_test_innodb_lock_name on test_innodb_lock(name);

5.5、行锁基本演示

在这里插入图片描述

5.6、无索引行锁升级为表锁

如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样。

查看当前表的索引 : show index from test_innodb_lock ;

在这里插入图片描述

由于 执行更新时 , name字段本来为varchar类型, 我们是作为数组类型使用,存在类型转换,索引失效,最终行锁变为表锁 ;

5.7、间隙锁危害

当我们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进行加锁; 对于键值在条件范围内但并不存在的记录,叫做 “间隙(GAP)” , InnoDB也会对这个 “间隙” 加锁,这种锁机制就是所谓的 间隙锁(Next-Key锁) 。

示例 :

在这里插入图片描述

5.8、InnoDB 行锁争用情况

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: 系统启动后到现在总共等待的次数


当等待的次数很高,而且每次等待的时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手制定优化计划。

5.9、总结

InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面带来了性能损耗可能比表锁会更高一些,但是在整体并发处理能力方面要远远由于MyISAM的表锁的。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势。

但是,InnoDB的行级锁同样也有其脆弱的一面,当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不能比MyISAM高,甚至可能会更差。

优化建议:

  • 尽可能让所有数据检索都能通过索引来完成,避免无索引行锁升级为表锁。
  • 合理设计索引,尽量缩小锁的范围
  • 尽可能减少索引条件,及索引范围,避免间隙锁
  • 尽量控制事务大小,减少锁定资源量和时间长度
  • 尽可使用低级别事务隔离(但是需要业务层面满足需求)

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

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

相关文章

机器学习模型-BUPA liver disorders-探索饮酒与肝炎关系(论文,科研,医疗信息化诊断系统用)

肝炎是由细菌、病毒、寄生虫、酒精、药物、化学物质、自身免疫等多种致病因素引起的肝脏炎症的统称。儿童及成年人均可患病,病毒感染导致的病毒性肝炎较为常见。 过渡饮酒是肝炎重要因素 过渡饮酒会引发下述血检指标异常,暗示肝炎发生。 酒精相关性肝病…

使用Nordic的nrf52840实现蓝牙DFU过程

需要用到的软件: 交叉编译环境:gcc-arm-none-eabi MinGW:下载 Python:下载 micro-ecc源码:下载 nRFUtil:下载或者直接使用python的pip来安装 手机app:nRF Toolbox或者nRF Connect 安装 gcc-…

【爬虫】JS调试解决反爬问题系列3—sign破解

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…

LabVIEW如何减少下一代测试系统中的硬件过时 1

LabVIEW如何减少下一代测试系统中的硬件过时 1 许多测试系统的问题是,整个系统运行的时间必须超过单个系统组件的支持时间。有时被测试的设备有几十年的有效使用寿命,而许多测试仪器已经过时,在5年或更短的时间后就不再支持了。其他时候&…

技能梳理32@电源防反接电路+光耦隔离电路+串口磁耦隔离电路

电源防反接电路 CN2是个防反接插座; F1是个自恢复保险丝; MB6S是个整流桥电路,主要是这个模块实现的防反接效果; SPX3819是个电平转换模块,封装挺小的;LDO-EN是用来控制SPX3819是否使能的; …

等保2.0参与医院网络安全管理的重要性

随着现代医院 IT 技术架构的演变、新兴技术的引入,来自医院内外部的各种安全风险不断出现,对医院网络安全提出了更多挑战,医院网络安全在技术层面和管理层面都亟待完善。为此,借鉴相关法律法规、行业标准等,提出提升现…

Web前端开发神器WebStorm v2022.3发布——支持新的CSS功能

WebStorm是一款JavaScript 开发工具。被广大中国JS开发者誉为"Web前端开发神器""最强大的HTML5编辑器""最智能的JavaSscript IDE"等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。 WebStorm v2022.3官方正式版下载…

百度工程师教你玩转设计模式(装饰器模式)

作者 | 北极星小组 想要写好代码,设计模式(Design Pattern)是必不可少的基本功,设计模式是对面向对象设计(Object Oriented Design)中反复出现的一类问题的一种解决方案,本篇介绍装饰器模式&am…

(第一章)OpGL超级宝典学习:配置和超级宝典相同的工作环境

目录前言配套资源配置解压文件夹复制资源HOWTOBUILD什么是CMake什么是GLFW安装CMake开始构建build glfw生成debug和release的lib库build sample推送结语前言 最近发现学习好像到了一定的瓶颈,马上要到2023年了,想要在新的一年开始后对自己有一定的突破&a…

Kubernetes 实现自动扩容和自愈应用实践

Kubernetes 自动扩容和自愈 tags: 实践 文章目录Kubernetes 自动扩容和自愈1. 背景2. 准备3. kind 部署 kubernetes4.实践4.1 部署 deployment4.2 创建 Service4.3 创建 Ingress4.4 部署 Ingress-nginx4.5 K8s 实现自愈4.6 k8s 实现自动扩容5. 其他1. 背景 在生产非 kubernet…

java进阶—List

上节回顾 List 是一个有序的,允许重复的Collection,其下的子类主要有 ArrayList LinkedList,Vector(这个官方不推荐使用) 那么同为list的子类,ArrayList 跟 LinkedList 有什么区别呢? 这里就涉及到了list的底层两种实现方式&…

《计算机体系结构量化研究方法》第2章-存储器层次结构设计 2.1 引言

一、概述 1、存储器层次结构:层次由速度和容量各不相同的存储器组成。 2、存储器层次结构被分为几个级别——离处理器越近,容量越小速度越快。 3、包含性质:大多数情况下,低层级存储器中的数据是上一级存储器中数据的超集。比如…

基于RSA的数字签名设计与实现

信息安全课程的第二个实验,主要是用java、js,前端页面用的html写的。 页面成果展示: 基本公私钥生成 实验环境为win10系统,使用git命令行工具——git bash生成公私钥。生成私钥,密钥长度为1024bit并从私钥中提取公钥 …

如何在 Spring Boot 项目中开启 “热部署“

目录 1. 添加热部署框架支持 2. 设置当前项目 Settings 和新项目 Settings 开启项目自动编译 3. 开启运行中热部署 4. 使用 Debug 启动项目 (社区版 IDEA) 1. 添加热部署框架支持 在 pom.xml 中添加如下框架引用: <dependency><groupId>org.springframework.b…

vue3中常用的三种组件传值方式

比较大型的项目中经常会涉及到多个组件之间进行传值&#xff0c;所以对之前用过的一些传值方法做个笔记&#xff0c;还有就是对不同的情况下需要使用哪一种传值方法更合适的思维进行一个总结 vue3中常用的三种组件传值方式mitt依赖注入pinia总结mitt 因为vue3去掉了全局事件总…

qt实现的pdf阅读器(二)--XpdfReader在linux下的编译

目录 1.简介 2.需求说明 3.编译 3.3. 下载源码 3.2. 移植安装包和依赖库 3.2.1 准备工作 3.3.2 了解 3.3.3 编译并安装zlib 3.3.4 编译并安装libpng 3.3.5 编译并安装lcms 3.3.6 编译并安装freetype 3.3.7 编译xpdf 3.3.8 查看运行编译好的xpdf 1.简介 Xpdf 是一个免…

我以为自己MySQL够牛逼了,直到看到了Alibaba的面试题

前言 众所周知&#xff0c;简历上“了解&#xff1d;听过名字&#xff1b;熟悉&#xff1d;知道是啥&#xff1b;熟练&#xff1d;用过&#xff1b;精通&#xff1d;做过东西”。 相信大家对于MySQL的索引都不陌生&#xff0c;索引(Index)是帮助MySQL高效获取数据的数据结构。…

SpringBoot Disruptor框架遇到的问题

1.消息重复消费问题 问题描述&#xff1a; 项目中启动了多个消费者,测试中发现同一条消息被多次消费。 解决方案&#xff1a; ①幂等方案处理 ②disrutor提供了不同的处理机制&#xff1a; 自定义消费者实现EventHandler接口,他是属于重复消费&#xff0c; 自定义消费者实现W…

SVN培训笔记(下拉项目、同步修改、添加文件、修改文件、删除文件、改名文件等)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/128417196 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

【矩阵论】7. 范数理论——非负/正矩阵

7.5 非负/正矩阵 7.5.1 定义 a. 非负/正矩阵定义 一个实矩阵 A(aij)∈RmnA(a_{ij})\in R^{m\times n}A(aij​)∈Rmn 若对每一 iii 和 jjj &#xff0c;aij≥0a_{ij}\ge 0aij​≥0 &#xff0c;则称A是非负矩阵&#xff0c;A≥0A\ge 0A≥0 若对每一 iii 和 jjj &#xff0c;…