【转】【MySQL】事务与锁(四):行锁到底锁住的是什么?记录?字段?索引?

首先我们有三张表t1,t2,t3,它们都是只有两个字段, int类型的id和varchar类型的name;区别是t1没有索引,t2有主键索引,t3有唯一索引。
在这里插入图片描述

再强调一次,在实验前必须提前关闭自动提交,set autocommit=off。然后show variables like 'autocommit'查看自动提交是否是off。

我们先假设InnoDB的锁锁住了是一行数据或者一条记录。

1.假设锁住记录

1.1 实验一:没有索引的表(t1)

这个实验操作是操作没有索引的t1,t1里面有4条数据:1、2、3、4。

现在我们在两个会话里面手工开启两个事务。在第一个事务里面,我们通过where id =1 锁住第一行数据。在第二个事务里面,我们尝试给id=3的这一行数据加锁,大家觉得能成功吗?

Transaction1Transaction2
Begin; 
SELECT * FROM t1 where id=1 FOR UPDATE; 
 Begin;
 SELECT * FROM t1 where id=3 FOR UPDATE; // BLOCKED
 INSERT INTO t1 (id, name) VALUES (5, ‘5’); // BLOCKED

这就有点奇怪了,第一个事务锁住了id=1的这行数据,为什么我不能操作id=3的数据呢?我们再来操作一条不存在的数据,插入id=5。它也被阻塞了。实际上这里整张表都被锁住了。所以,我们的第一个猜想被推翻了,InnoDB的锁锁住的应该不是Record。

那为什么在没有索引或者没有用到索引的情况下,会锁住整张表?这个问题我们先留在这里。下面继续看第二个实验。

1.2 实验二:有主键索引的表(t2)

我们先看一下t2的表结构。字段是一样的,不同的地方是id上创建了一个主键索引。里面的数据是 1、4、7、10。

Transaction1Transaction2
Begin; 
SELECT * FROM t2 where id=1 FOR UPDATE; 
 Begin;
 SELECT * FROM t2 where id=1 FOR UPDATE; // BLOCKED
 SELECT * FROM t2 where id=4 FOR UPDATE; // OK

第一种情况,使用相同的id值去加锁,冲突;使用不同的id加锁,可以加锁成功。

那么出现问题了,从实验一中得到锁定的不是一行数据,但是实验二操作不同记录的数据又可以成功,那有没有可能是锁住了id的这个字段呢?

2.假设锁住字段

我们看一下 t3 的表结构。字段还是一样的, id上创建了一个主键索引,name上创建了一个唯一索引。里面的数据是1、4、7、10。

在第一个事务里面,我们通过name字段去锁定值是4的这行数据。在第二个事务里面,尝试获取一样的排它锁,肯定是失败的,这个不用怀疑。在这里我们怀疑InnoDB锁住的是字段,所以这次我换一个字段,用id=4去给这行数据加锁,大家觉得能成功吗?

Transaction1Transaction2
Begin; 
SELECT * FROM t3 where name=‘4’ FOR UPDATE; 
 Begin;
 SELECT * FROM t3 where name=‘4’ FOR UPDATE; // BLOCKED
 SELECT * FROM t3 where id=4 FOR UPDATE; // BLOCKED

很遗憾,又被阻塞了,说明锁住的是字段的这个推测也是错的,否则就不会出现第一个事务锁住了name,第二个字段锁住id失败的情况。

既然锁住的不是record,也不是column, InnoDB里面锁住的到底是什么呢?

3.其实,锁的是索引

在这三个案例里面,我们要去分析一下他们的差异在哪里,也就是这三张表的结构,是什么区别导致了加锁的行为的差异?其实答案就是索引。 InnoDB的行锁,就是通过锁住索引来实现的

那索引又是个什么东西?为什么它可以被锁住?我们在 【MySQL】详谈索引存储结构推演过程 已经分析过了。那么我们还有两个问题没有解决:

问题一:为什么表里面没有索引的时候,实验一锁住一行数据会导致锁表?或者说,如果锁住的是索引,一张表没有索引怎么办?所以,一张表有没有可能没有索引?

  1. 如果我们定义了主键(PRIMARYKEY),那么 InnoDB 会选择主键作为聚集索引
  2. 如果没有显式定义主键,则 InnoDB 会选择第一个不包含有 NULL 值的唯一索引作为主键索引
  3. 如果也没有这样的唯一索引,则 InnoDB 会选择内置 6 字节长的 ROWID 作为隐藏的聚集索引,它会随着行记录的写入而主键递增

所以,实验一为什么锁表,是因为查询没有使用索引,会进行全表扫描,然后把每一个隐藏的聚集索引都锁住了。

问题二:实验二为什么通过唯一索引给数据行加锁,主键索引也会被锁住?

在辅助索引里面, 索引存储的是二级索引和主键的值。 比如name=4,存储的是name的索引和主键id的值4。而主键索引里面除了索引之外,还存储了完整的数据。所以我们通过辅助索引锁定一行数据的时候,它跟我们检索数据的步骤是一样的,会通过主键值找到主键索引,然后也锁定。

在这里插入图片描述

 

复杂官网的一句话,A record lock is a lock on an index record,是不是只有【记录锁】是锁索引,其他锁是锁住行或表?

回复:行锁、表锁是对于锁粒度而言的,是一对最广泛的概念。表锁的实现很好想,就是需要一个标志来记录当前有没有事务已经来操做表了。而行锁的实现是锁的索引,根据锁索引的范围又可以分为记录锁、间隙锁、临键锁。 比如说我们修改一个数据库已经有的记录,那直接锁相应索引就行(记录锁);再比如我们给一张有两条数据的表(id=1,id=10)进行范围查询并加锁 where id>2 and id < 5 for update,此时命中了一个不存在数据的区间(2,5),这时该锁哪?是锁两个索引之间的整个区间(1,10),这就是间隙锁。临键锁=记录锁+间隙锁,这里就不说了,可以看我的这篇文章 https://blog.csdn.net/weixin_43935927/article/details/109410420

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

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

相关文章

【编译原理】理解BNF

BNF范式 下面来自百度百科&#xff1a; 巴科斯范式&#xff08;BNF&#xff09;所描述的语法是与上下文无关的。它具有语法简单&#xff0c;表示明确&#xff0c;便于语法分析和编译的特点。 源码解析使用的算法就是BNF或者其改进算法。 什么是上下文无关文法呢&#xff1f; …

gibmacos 网络加速_黑苹果教程续集,利用EFI在线安装MacOS

本内容来源于什么值得买APP&#xff0c;观点仅代表作者本人 &#xff5c;作者&#xff1a;qianseyue创作立场声明&#xff1a;本人非某领域/某品牌从业人员&#xff0c;有机会学到一些专业知识。然而每个人站在不同立场&#xff0c;内容就会有所偏重&#xff0c;客观与否还请大…

【转】1.1【MySQL】基本SQL语句大全

1.库操作 登录数据库&#xff08;-h -u -p -P都不需要空格&#xff09; mysql -h {ip} -u {username} -p{password} -P {port} # -h ip默认是 localhost # -p 指定密码时中间不要空格&#xff0c;比如 -p123456 # -P 端口默认是 3306 1.1 增 create database 库名1.2 删 dr…

【GUI开发】图像处理类软件的浏览功能实现模型

图像处理软件包括但不限于&#xff1a; 图片浏览器&#xff0c;2D地图浏览器、图片编辑器等软件。 为了处理大分辨率图片&#xff0c;一般采用GDAL加载图像&#xff0c;GDAL可以动态加载图像的一部分&#xff0c;可以建立图像金字塔&#xff0c;优化加载速度。 一般的图像处理…

自动事务_JDBC进阶(二)事务编程

一、事务简介事务是用户定义的一个数据库操作序列&#xff0c;这些操作要么全做&#xff0c;要么全不做&#xff0c;是一个不可分割的工作单位。事务具有ACID特性&#xff1a;原子性&#xff08;Atomicity&#xff09; —— 原子性是指事务是一个不可分割的工作单位&#xff0c…

【转】事务和锁机制是什么关系? 开启事务就自动加锁了吗?

数据库锁 因为数据库要解决并发控制问题。在同一时刻&#xff0c;可能会有多个客户端对同一张表进行操作&#xff0c;比如有的在读取该行数据&#xff0c;其他的尝试去删除它。为了保证数据的一致性&#xff0c;数据库就要对这种并发操作进行控制&#xff0c;因此就有了锁的概…

【精华】详解Qt中的内存管理机制

前言 内存管理&#xff0c;是对软件中内存资源的分配与释放进行有效管理的方法和理论。 众所周知&#xff0c;内存管理是软件开发的一个重要的内容。软件规模越大&#xff0c;内存管理可能出现的问题越多。如果像C语言一样手动地管理内存&#xff0c;一会给开发人员带来巨大的…

a标签里面设置onclick_实现a标签中的各种点击(onclick)事件的方法

我们常用的在a标签中有点击事件&#xff1a;1. a href"javascript:js_method();"这是我们平台上常用的方法&#xff0c;但是这种方法在传递this等参数的时候很容易出问题&#xff0c;而且javascript:协议作为a的href属性的时候不仅会导致不必要的触发window.onbefore…

【转】2.1【MySQL】运行原理(一):查询sql的执行过程及MySQL架构分析

MySQL的发展历史和版本分支&#xff1a; 时间里程碑1996 年MySQL1.0 发布。它的历史可以追溯到 1979 年&#xff0c;作者 Monty 用 BASIC 设计的一个报表工具。1996 年 10 月3.11.1 发布。MySQL 没有 2.x 版本。2000 年ISAM 升级成 MyISAM 引擎。MySQL 开源。2003 年MySQL4.0 …

docker多个容器一起打包_如何链接多个Docker容器并封装结果?

在另一个容器中运行容器意味着在Docker容器中运行Docker引擎.这被称为Docker-in-Docker的dind,我强烈反对它.你可以在线搜索’dind’并发现为什么在大多数情况下这是一个坏主意,但由于它不是你问题的主要对象,我不会进一步扩展这个主题.在同一容器中运行node.js进程和neo4j进程…

【转】2.2【MySQL】运行原理(二):InnoDB 内存结构、磁盘结构及update sql执行过程分析

前一篇讲完了查询流程&#xff0c;我们是不是再讲讲更新流程、插入流程和删除流程&#xff1f;在数据库里面&#xff0c;我们说的update操作其实包括了更新、插入和删除。如果大家有看过MyBatis的源码&#xff0c;应该知道Executor里面也只有doQuery()和doUpdate()的方法&#…

单片机ch2o程序_基于单片机的室内甲醛浓度检测系统

基于单片机的室内甲醛浓度检测系统田秀荣【期刊名称】《山西电子技术》【年(卷),期】2014(000)003【摘要】Aseveryoneknows,theharmfulgasremainedbyhousedecorationandinferiorfurnitureismainlyformaldehydewhichhasgreat harm to human body health , many diseases is rele…

【转】MySQL中select * for update锁表的问题

MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock&#xff0c;所以只有「明确」的指定主键&#xff0c;MySQL才会执行Row lock (只锁住被选取的资料例) &#xff0c;否则MySQL将会执行Table Lock (将整个资料表单给锁住)。 举个例子: 假设有个表单produc…

apqp过程流程图范本_APQP项目资料清单excel格式(全套)

APQP项目开发全套资料明细表设施要求新增刀具验收报告 量具、试验装备 要求 量具试验装备清单 新增量具试验装备计划技术/生产 技术/质保 采购▲ ★ ▲ ▲2.162.17项目组 新设备、工装和 A-3新设备、工装、刀具和试验 试验装置评审 装置检查清单 财务/技术2.18 新产品成本预算 …

【转】2.3【MySQL】运行原理(三)InnoDB 逻辑存储结构

MySQL的存储结构分为5级&#xff1a;表空间、段、簇、页、行。 1.表空间 TableSpace 上篇【MySQL】从InnoDB的内存结构、磁盘结构到update sql执行过程分析 在磁盘结构部分就说过了&#xff0c;表空间可以看做是InnoDB 存储引擎逻辑结构的最高层&#xff0c;所有的数据都存放在…

layui templet格式化_layui数据表格日期如何格式化成2012-12-30这样的?

test学生评优评先系统学生信息管理学生信息查询学生信息添加注册登录查看编辑删除$(function () {layui.use("table", function () {var $table layui.table;//第一个实例$table.render({elem: #stu,height: 300,//数据接口,url: /stu/student/getAllClazz,//开启分…

【转】【MySQL】运行原理(四):重做日志(redo log),回滚日志(undo log),二进制日志(binlog)

MySQL中有六种日志文件&#xff0c;分别是&#xff1a;重做日志&#xff08;redo log&#xff09;、回滚日志&#xff08;undo log&#xff09;、二进制日志&#xff08;binlog&#xff09;、错误日志&#xff08;errorlog&#xff09;、慢查询日志&#xff08;slow query log&…

python 读中文乱码_python字符乱码的解决小结

引言无论学习什么程序语言&#xff0c;字符串这种数据类型总是着有非常重要。然而最近在学习python这门语言&#xff0c;想要显示中文&#xff0c;总是出现各种乱码。于是在网上查了很多资料&#xff0c;各说纷纭&#xff0c;我也尝试了许多的方法&#xff0c;有时候可以正常显…

【转】关于国密算法 SM1,SM2,SM3,SM4 的笔记

国密即国家密码局认定的国产密码算法。主要有SM1&#xff0c;SM2&#xff0c;SM3&#xff0c;SM4。密钥长度和分组长度均为128位。 SM1 为对称加密。其加密强度与AES相当。该算法不公开&#xff0c;调用该算法时&#xff0c;需要通过加密芯片的接口进行调用。 SM2为非对称加密…

ntnub原理怎么看_老电工由浅入深带你入门学PLC的工作原理和梯形图的编程规则...

PLC编程怎么学&#xff1f;很难吗&#xff1f;工控小白怎么入门学习PLC&#xff1f;需要为学习PLC编程做哪些准备&#xff1f;学习PLC编程时&#xff0c;前期一定要积累相关的理论知识&#xff0c;有了一定的基础&#xff0c;基础打扎实之后就是多练习了。今天推荐的重点&#…