MySQL锁机制

概述

  作为一名程序员(我是java开发),是一个绕不开的话题。有读锁、写锁、排他锁、共享锁、红锁、可重入锁、自旋锁、公平锁、乐观锁、分段锁、偏向锁等等(其实有些是一个意思)。今天这里要说的是Mysql的锁机制(主要是innodb),涉及到的主要是读锁、写锁、意向锁、自增锁。

表锁和行锁

1、介绍

  在对锁模式进行说明之前,先说明一下这个表锁和行锁。表锁是对整张数据表来进行加锁,一般是 DDL 处理时使用,由Mysql server提供;而行锁则是锁定某一行或者某几行,或者行与行之间的间隙,主要是由存储引擎来提供。

2、引擎说明

  mysql中常用的InnoDB引擎支持行锁和表锁,而 MyISAM 则只能使用 MySQL Server 提供的表锁。

  • MyISAM 和 MEMORY 存储引擎采用的是表级锁(table-level locking)
  • BDB 存储引擎采用的是页面锁(page-level locking),但也支持表级锁
  • InnoDB 存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。

默认情况下,表锁和行锁都是自动获得的,不需要额外的命令。但是在有的情况下, 用户需要明确地进行锁表或者进行事务的控制,以便确保整个事务的完整性,这样就需要使用事务控制和锁定语句来完成。

3、不同粒度的比较
  • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。这些存储引擎通过总是一次性同时获取所有需要的锁以及总是按相同的顺序获取表锁来避免死锁。表级锁更适合于以查询为主,并发用户少,只有少量按索引条件更新数据的应用,如Web 应用

在这里插入图片描述

  • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。最大程度的支持并发,同时也带来了最大的锁开销。在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,这就决定了在 InnoDB 中发生死锁是可能的。并且只在存储引擎层实现,而Mysql服务器层没有实现。行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。

在这里插入图片描述

  • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。页级锁定主要是BerkeleyDB 存储引擎。

锁的说明

1、读锁

读锁,又称共享锁(Share locks,简称 S 锁),加了读锁的记录,所有的事务都可以读取,但是不能修改,并且可同时有多个事务对记录加读锁。

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

2、写锁

写锁,又称排他锁(Exclusive locks,简称 X 锁),或独占锁,对记录加了排他锁之后,只有拥有该锁的事务可以读取和修改,其他事务都不可以读取和修改,并且同一时间只能有一个事务加写锁。

排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

3、自增锁

AUTOINC锁又叫自增锁(一般简写成AI锁),是一种表锁,当表中有自增列(AUTOINCREMENT)时出现。当插入表中有自增列时,数据库需要自动生成自增值,它会先为该表加AUTOINC表锁,阻塞其他事务的插入操作,这样保证生成的自增值肯定是唯一的。AUTOINC 锁具有如下特点:

  • AUTO_INC 锁互不兼容,也就是说同一张表同时只允许有一个自增锁;
  • 自增值一旦分配了就会+1,如果事务回滚,自增值也不会减回去,所以自增值可能会出现中断的情况。
4、意向锁

由于表锁和行锁虽然锁定范围不同,但是会相互冲突。所以当你要加表锁时,势必要先遍历该表的所有记录,判断是否加有排他锁。这种遍历检查的方式显然是一种低效的方式,MySQL 引入了意向锁,来检测表锁和行锁的冲突。

意向锁也是表级锁,也可分为读意向锁(IS 锁)和写意向锁(IX 锁)。当事务要在记录上加上读锁或写锁时,要首先在表上加上意向锁。这样判断表中是否有记录加锁就很简单了,只要看下表上是否有意向锁就行了。

意向锁之间是不会产生冲突的,也不和 AUTO_INC 表锁冲突,它只会阻塞表级读锁或表级写锁,另外,意向锁也不会和行锁冲突,行锁只会和行锁冲突。

意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的 IS 锁。

意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的 IX 锁。

InnoDB加锁

-- 创建表
create table user
(id   int not null auto_increment primary key,name varchar(255),age  int
);
INSERT INTO test.user (id, name, age) VALUES (1, 'A', 1);
意向锁
  • 是 InnoDB 自动加的, 不需用户干预。
  • 对于 UPDATE、 DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);

对于普通 SELECT 语句,InnoDB不会加任何锁。事务可以通过以下语句显式给记录集加共享锁或排他锁:

-- 如果你这个地方不提交,那么这条数据在数据表还是旧数据,而且无法修改。【排他锁】(这里为了测试所开启使用了事务)
START TRANSACTION; -- 开始事务
update user set name='BB' where id=1;COMMIT;-- 提交事务
-- 未提交之前,通过这个可以查看意向锁(mysql 8之后是这个语句,8之前的请自行百度)
SELECT * FROM performance_schema.data_locks;
共享锁(S):

SELECT * FROM table_name WHERE … LOCK IN SHARE MODE。 其他 session 仍然可以查询记录,并也可以对该记录加 share mode 的共享锁。但是如果当前事务需要对该记录进行更新操作,则很有可能造成死锁。

-- 如果你这个地方不提交,你可以用其他方式读取,但是无法修改。【共享锁】(这里为了测试所开启使用了事务)
START TRANSACTION; -- 开始事务
select * from user where id=1 LOCK IN SHARE MODE;COMMIT;-- 提交事务
-- 重启线程执行共享查询操作是没有问题的
-- 但是如果你在上面未提交执行,重启线程执行会产生排他锁的语句,会导致锁等待。【如果你在同一个线程事务下操作,会导致死锁】
update user set name='FF' where id=1;
-- 通过这个可以查看到锁等待的数据(mysql 8之后是这个语句,8之前的请自行百度)
SELECT * FROM performance_schema.data_lock_waits;
排他锁(X):

SELECT * FROM table_name WHERE … FOR UPDATE。其他 session 可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁

-- 如果你这个地方不提交,事务下的锁内操作无法读取,并且其他语句无法修改。【排他锁】(这里为了测试所开启使用了事务)
START TRANSACTION; -- 开始事务
select * from user where id=1 FOR UPDATE ;COMMIT;-- 提交事务
-- 重启一个线程执行,如果上面没有提交,这个共享锁无法添加查询到任何数据
select * from user where id=1 LOCK IN SHARE MODE;
-- 通过这个可以查看到锁等待的数据(mysql 8之后是这个语句,8之前的请自行百度)
SELECT * FROM performance_schema.data_lock_waits;
间隙锁:
  1. 防止幻读,以满足相关隔离级别的要求;
  2. 满足恢复和复制的需要。

死锁

-- 这个的执行会产生死锁
START TRANSACTION; -- 开始事务
select * from user where id=1 LOCK IN SHARE MODE;
select * from user where id=1 FOR UPDATE ;
COMMIT ;-- 提交事务
-- 查看最近一次死锁信息(mysql 8)
SHOW ENGINE INNODB STATUS; 
死锁产生:

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。

当事务试图以不同的顺序锁定资源时,就可能产生死锁。多个事务同时锁定同一个资源时也可能会产生死锁。

锁的行为和顺序和存储引擎相关。以同样的顺序执行语句,有些存储引擎会产生死锁有些不会——死锁有双重原因:真正的数据冲突;存储引擎的实现方式。

检测死锁:

数据库系统实现了各种死锁检测和死锁超时的机制。InnoDB存储引擎能检测到死锁的循环依赖并立即返回一个错误。

死锁恢复:

死锁发生以后,只有部分或完全回滚其中一个事务,才能打破死锁,InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。所以事务型应用程序在设计时必须考虑如何处理死锁,多数情况下只需要重新执行因死锁回滚的事务即可。

外部锁的死锁检测:

发生死锁后,InnoDB 一般都能自动检测到,并使一个事务释放锁并回退,另一个事务获得锁,继续完成事务。但在涉及外部锁,或涉及表锁的情况下,InnoDB 并不能完全自动检测到死锁, 这需要通过设置锁等待超时参数 innodb_lock_wait_timeout 来解决

死锁影响性能:

死锁会影响性能而不是会产生严重错误,因为InnoDB会自动检测死锁状况并回滚其中一个受影响的事务。在高并发系统上,当许多线程等待同一个锁时,死锁检测可能导致速度变慢。 有时当发生死锁时,禁用死锁检测(使用innodb_deadlock_detect配置选项)可能会更有效,这时可以依赖innodb_lock_wait_timeout设置进行事务回滚。

InnoDB避免死锁:

为了在单个InnoDB表上执行多个并发写入操作时避免死锁,可以在事务开始时通过为预期要修改的每个元祖(行)使用SELECT … FOR UPDATE语句来获取必要的锁,即使这些行的更改语句是在之后才执行的。

在事务中,如果要更新记录,应该直接申请足够级别的锁,即排他锁,而不应先申请共享锁、更新时再申请排他锁,因为这时候当用户再申请排他锁时,其他事务可能又已经获得了相同记录的共享锁,从而造成锁冲突,甚至死锁。

如果事务需要修改或锁定多个表,则应在每个事务中以相同的顺序使用加锁语句。 在应用中,如果不同的程序会并发存取多个表,应尽量约定以相同的顺序来访问表,这样可以大大降低产生死锁的机会。

通过SELECT … LOCK IN SHARE MODE获取行的读锁后,如果当前事务再需要对该记录进行更新操作,则很有可能造成死锁。

改变事务隔离级别

如果出现死锁,可以用 SHOW ENGINE INNODB STATUS 命令来确定最后一个死锁产生的原因。返回结果中包括死锁相关事务的详细信息,如引发死锁的 SQL 语句,事务已经获得的锁,正在等待什么锁,以及被回滚的事务等。据此可以分析死锁产生的原因和改进措施。

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

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

相关文章

excel导入功能(适用于vue和react都可)

如图所示&#xff08;需求&#xff09;&#xff1a;点击导入excel后&#xff0c;数据自动新增到列表数据内 这里以vue3 andt 为例 template 标签内代码 &#xff1a; <a-uploadname"file":multiple"true":show-upload-list"false":customR…

3.3 ss-sp寄存器,栈的push和pop指令

汇编语言 1. 栈 栈是一种具有特殊的访问方式的存储空间它的特殊性就在于&#xff0c;最后进入这个空间的数据&#xff0c;最先出去。即先进后出 1.1 栈的基本操作 入栈&#xff1a;入栈就是将一个新的元素放到栈顶出栈&#xff1a;出栈就是从栈顶取出一个元素栈顶的元素总是…

Docker简单认识

目录 一、Docker概述 二、容器技术 2.1 容器与虚拟机的比较 2.2 容器和应用程序的比较 三、Docker和容器的关系 四、Docker和操作系统 五、总结 一、Docker概述 Docker 是一个开源的平台&#xff0c;用于开发、运送和运行应用程序。通过使应用程序与底层系统隔离&#x…

第2章 信息技术基础

本章学习要点 全面了解医院信息系统建设所涉及的主要信息技术以及这些技术的应用情况。 计算机与网络、信息技术与信息系统、数字媒体与数据存储技术、条形码(二维码)、RFID技术、云计算、APP技术 1.XML 可扩展标记语言与Access&#xff0c;Oracle和SQL Server等数据库不同…

【机器学习-01】机器学习基本概念与建模流程

机器学习的过程本质上是一个不断通过数据训练来提升模型在对应评估指标上表现的过程。在此过程中&#xff0c;为模型提供有效的反馈并基于这些反馈进行持续的调整是至关重要的。只有当这个过程顺利进行时&#xff0c;模型才能得到有效的训练&#xff0c;机器才能真正实现学习。…

修改vscode中代码的注释颜色

打开C盘、进入user目录&#xff0c;然后依次打开以下图片中的文件夹&#xff0c;在指定的文件中进行修改。 1. 2. 3. 4. 5. 6.

2049.不容易系列之(4)——考新郎

2048的升级 当nm时则全排错&#xff0c;与上题一样 当n>m时&#xff0c;则有n-m个是排对的&#xff0c;剩下m个全错 import java.util.*;public class Main {public static void main(String[] args) {Scanner scannernew Scanner(System.in);int num scanner.nextInt()…

解决ubuntu 22.04新内核6.5.0-15无法编译NVIDIA显卡驱动

这里的新内核应该包括6.5.*系列的 文章目录 遇到的问题&#xff1a; 遇到的问题&#xff1a; 今天我在安装NVIDIA显卡驱动发现了一个问题&#xff0c;主要日志如下所示&#xff1a; make[3]: *** [scripts/Makefile.build:251: /tmp/selfgz1310041/NVIDIA-Linux-x86_64-550.5…

昂贵的日用品和廉价的奢侈品

不同消费支出的心理账户之间具有非替代性 不同的消费支出分置在不同的心理账户中&#xff0c;不同消费心理账户的开支会受到所在账户预算约束的影响。 心理账户的预算控制机制 人们在分配总预算时&#xff0c;会将预算分门别类地分配到具体的心理账户中去。对于所有超过心理账…

Python+requests+excel 接口自动化测试框架

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、接口自动化测试框架 二、工程目录 三、Excel测试用例设计 四、基础数据base 封装post/get&a…

centos7磁盘管理,lvm挂载、扩容

一、centos7 磁盘挂载 默认盘符格式 centos7 默认文件格式xfscentos6 默认文件格式ext4centos5 默认文件格式ext3 1、/dev/vdb和/dev/mapper/lvm-data对比 1&#xff09;/dev/vdb /dev/vdb通常表示一个裸的块存储设备&#xff0c;比如一个硬盘或者虚拟机中的一个虚拟硬盘。…

【图像分类】基于深度学习的人脸表情识别(开心、悲伤、生气三个类别,ResNet网络)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内,不想订阅专栏的兄弟们可以私信…

Uni-app跟学笔记(五):uni-ui组件库的使用、项目打包(小程序、h5、APP)

文章目录 1&#xff09;uni-ui组件库的使用2&#xff09;项目打包1&#xff1a;微信小程序打包2&#xff1a;h5打包3&#xff1a;安卓打包 本博客为 uni-app 此门课的跟学笔记&#xff0c;目的是便于个人复习和对知识快速索引&#xff0c;源码素材可在均可在视频评论区找到 1&a…

C语言函数—递归理解和练习

练习&#xff1a; 编写函数不允许创建临时变量&#xff0c;求字符串的长度。 我们看到这道题&#xff0c;第一个想到的是不是strlen int main() {char[] "bit";//[b][i][t][\0]//里面一共4个字符&#xff08;包括结尾的、0&#xff09;但是我们的strlen函数并不会计…

使用USART2收发数据时,接收数据正常,但数据发不出去

今天使用串口2与上位机通信&#xff0c;发现问题&#xff1a; 单片机接收上位机的数据正常&#xff0c;但发送数据给上位机时&#xff0c;却总是失败。 为了排除程序的干扰&#xff0c;我构造了一个数组&#xff0c;循环发送这串数据&#xff1a; void UartSend(uint8_t *pS…

微服务学习day02 -- nacos配置管理 -- Feign远程调用 -- Gateway服务网关

0.学习目标 1.Nacos配置管理 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.1.统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就会让人抓狂&#xff0c;而且很容易出错。我们需要一种统一配置管理…

网络安全之URL过滤

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; URL过滤是一种针对用户的URL请求进行上网控制的技术&#xff0c;通过允许或禁止用户访问某些网页资源&#xff0c;达到规范上网行为和降低安全风险…

elasticsearch篇:DSL查询语法

1.DSL查询文档 众所周知&#xff0c;elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1. DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出…

Sublime Text简介、下载、安装、汉化、常用插件和激活——《跟老吕学Python编程》附录资料

Sublime Text简介、下载、安装、汉化、常用插件和激活——《跟老吕学Python编程》附录资料 Sublime Text 简介Sublime Text 下载、安装、汉化、常用插件和激活Sublime Text 官网Sublime Text 下载Sublime Text 安装1.安装2.右键菜单3.启动安装4.耐心等待5.安装完成 Sublime Tex…

计算机网络 谢希仁(001-2)

计算机网络-方老师 总时长 24:45:00 共50个视频&#xff0c;6个模块 此文章包含1.5到1.7的内容 1.5计算机网络类别 连通 共享 分类方法 广域网是边缘部分和核心部分的核心部分 以前是拨号连接 现在是光纤 总线型 星型 环形网 1.6计算机网络的性能 带上单位之后就不是…