mysql 值为0 但却被认为null_MySQL介于普通读和锁定读的加锁方式

在阅读本文前最好先看过三篇语句加锁分析文章:

  • 超全面MySQL语句加锁分析(上篇)(求转)
  • 超全面MySQL语句加锁分析(中篇)(求转)
  • 超全面MySQL语句加锁分析(下篇)(求转)

事前准备

为了故事的顺利发展,我们先建一个表,并向表中插入一些记录,下边是SQL语句:

CREATE TABLE hero (
number INT,
name VARCHAR(100),
country varchar(100),
PRIMARY KEY (number),
KEY idx_name (name)
) Engine=InnoDB CHARSET=utf8;

INSERT INTO hero VALUES
(1, 'l刘备', '蜀'),
(3, 'z诸葛亮', '蜀'),
(8, 'c曹操', '魏'),
(15, 'x荀彧', '魏'),
(20, 's孙权', '吴');

现在hero表中的记录情况就如下所示:

mysql> SELECT * FROM hero;
+--------+------------+---------+
| number | name | country |
+--------+------------+---------+
| 1 | l刘备 | 蜀 |
| 3 | z诸葛亮 | 蜀 |
| 8 | c曹操 | 魏 |
| 15 | x荀彧 | 魏 |
| 20 | s孙权 | 吴 |
+--------+------------+---------+
5 rows in set (0.01 sec)

现象

在小册答疑群里有一位同学提了一个问题:说是在READ COMMITTED隔离级别下发生了一件百思不得其解的事儿。好的,首先构造环境,将当前会话默认的隔离级别设置成READ COMMITTED

mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)

事务T1先执行:

# T1中,隔离级别为READ COMMITTED
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM hero WHERE country = '魏' FOR UPDATE;
+--------+---------+---------+
| number | name | country |
+--------+---------+---------+
| 8 | c曹操 | 魏 |
| 15 | x荀彧 | 魏 |
+--------+---------+---------+
2 rows in set (0.01 sec)

country列并不是索引列,所以本条语句执行时肯定是使用扫描聚簇索引的全表扫描方式来执行,EXPLAIN语句也证明了我们的想法:

mysql> EXPLAIN SELECT * FROM hero WHERE country = '魏' FOR UPDATE;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | hero | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 20.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.02 sec)

我们之前学过MySQL语句的加锁分析,知道在READ COMMITTED隔离级别下,如果采用全表扫描的方式执行查询语句时,InnoDB存储引擎将依次对每条记录加正经记录锁,在server层测试该记录是否符合WHERE条件,如果不符合则将加在该记录上的锁释放掉。本例中使用FOR UPDATE语句,肯定加的是X型正经记录锁。只有两条记录符合WHERE条件,所以最终其实只对这两条符合条件的记录加了X型正经记录锁(就是number列值为815的两条记录)。当然,我们可以使用SHOW ENGINE INNODB STATUS命令证明我们的分析:

mysql> SHOW ENGINE INNODB STATUS\G
... 省略了很多内容

------------
TRANSACTIONS
------------
Trx id counter 39764
Purge done for trx's n:o < 39763 undo n:o < 0 state: running but idle
History list length 36
Total number of lock structs in row lock hash table 1
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 281479653009568, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 281479653012832, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 39763, ACTIVE 468 sec
2 lock struct(s), heap size 1160, 2 row lock(s)
MySQL thread id 19, OS thread handle 123145470611456, query id 586 localhost 127.0.0.1 root
TABLE LOCK table `xiaohaizi`.`hero` trx id 39763 lock mode IX
RECORD LOCKS space id 287 page no 3 n bits 72 index PRIMARY of table `xiaohaizi`.`hero` trx id 39763 lock_mode X locks rec but not gap
Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 80000008; asc ;;
1: len 6; hex 000000009b4a; asc J;;
2: len 7; hex 80000001d3012a; asc *;;
3: len 7; hex 63e69bb9e6938d; asc c ;;
4: len 3; hex e9ad8f; asc ;;
Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 8000000f; asc ;;
1: len 6; hex 000000009b4a; asc J;;
2: len 7; hex 80000001d30137; asc 7;;
3: len 7; hex 78e88d80e5bda7; asc x ;;
4: len 3; hex e9ad8f; asc ;;
... 省略了很多内容

其中id39763的事务就是指T1,可以看出它为heap no值为45的两条记录加了X型正经记录锁(lock_mode X locks rec but not gap)。

然后再开启一个隔离级别也为READ COMMITTED的事务T2,在其中执行:

# T2中,隔离级别为READ COMMITTED
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM hero WHERE country = '吴' FOR UPDATE;
(进入阻塞状态)

很显然,这条语句也会采用全表扫描的方式来执行,会依次去获取每一条聚簇索引记录的锁。不过因为number值为8的记录已经被T1加了X型正经记录锁T2想得却得不到,只能眼巴巴的进行阻塞状态,此时的SHOW ENGINE INNODB STATUS也能证明我们的猜想(只截取了一部分):

---TRANSACTION 39764, ACTIVE 34 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1160, 1 row lock(s)
MySQL thread id 20, OS thread handle 123145471168512, query id 590 localhost 127.0.0.1 root Sending data
SELECT * FROM hero WHERE country = '吴' FOR UPDATE
------- TRX HAS BEEN WAITING 34 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 287 page no 3 n bits 72 index PRIMARY of table `xiaohaizi`.`hero` trx id 39764 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 80000008; asc ;;
1: len 6; hex 000000009b4a; asc J;;
2: len 7; hex 80000001d3012a; asc *;;
3: len 7; hex 63e69bb9e6938d; asc c ;;
4: len 3; hex e9ad8f; asc ;;

可以看到T2正在等待获取heap no4的记录上的X型正经记录锁(lock_mode X locks rec but not gap waiting)。

以上是很正常的阻塞逻辑,我们都可以分析出来,不过如果在T2中执行下边的UPDATE语句:

# T2中,隔离级别为READ COMMITTED
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE hero SET name = 'xxx' WHERE country = '吴';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

WTF? 竟然没有阻塞,就这么随意地执行成功了?同样的WHERE条件,同样的执行计划,怎么SELECT ... FOR UPDATEUPDATE语句的加锁情况不一样?

原因

哈哈,是的,的确不一样。其实MySQL支持3种类型的读语句:

  • 普通读(也称一致性读,英文名:Consistent Read)。

    这个就是指普通的SELECT语句,在末尾不加FOR UPDATE或者LOCK IN SHARE MODE的SELECT语句。普通读的执行方式是生成ReadView直接利用MVCC机制来进行读取,并不会对记录进行加锁。

    小贴士:对于SERIALIZABLE隔离级别来说,如果autocommit系统变量被设置为OFF,那普通读的语句会转变为锁定读,和在普通的SELECT语句后边加LOCK IN SHARE MODE达成的效果一样。

  • 锁定读(英文名:Locking Read)。

    这个就是事务在读取记录之前,需要先获取该记录对应的锁。当然,获取什么类型的锁取决于当前事务的隔离级别、语句的执行计划、查询条件等因素,具体可参见:超全面MySQL语句加锁分析(上篇)(求转)

  • 半一致性读(英文名:Semi-Consistent Read)。

    这是一种夹在普通读和锁定读之间的一种读取方式。它只在READ COMMITTED隔离级别下(或者在开启了innodb_locks_unsafe_for_binlog系统变量的情况下)使用UPDATE语句时才会使用。具体的含义就是当UPDATE语句读取已经被其他事务加了锁的记录时,InnoDB会将该记录的最新提交的版本读出来,然后判断该版本是否与UPDATE语句中的WHERE条件相匹配,如果不匹配则不对该记录加锁,从而跳到下一条记录;如果匹配则再次读取该记录并对其进行加锁。这样子处理只是为了让UPDATE语句尽量少被别的语句阻塞。

    小贴士:半一致性读只适用于对聚簇索引记录加锁的情况,并不适用于对二级索引记录加锁的情况。

很显然,我们上边所唠叨的例子中是因为事务T2执行UPDATE语句时使用了半一致性读,判断number列值为815这两条记录的最新提交版本的country列值均不为UPDATE语句中WHERE条件中的'吴',所以直接就跳过它们,不对它们加锁了。

本知识点容易被忽略,各位同学在工作过程中分析的时候别忘记考虑一下Semi-Consistent Read喔,码字不易,有帮助帮着转发喔,么么哒~

小青蛙历史文章(历史文章,不容错过):

关于事务和锁的一些细节个人所得税涨了,日子又拮据了一点补数到底是个什么玩意儿?从根儿上理解一下MySQL小册创作之心路历程虚拟内存是个啥 | 一分钟系列MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!

长按关注小青蛙,都是干货喔

83a961b89459c066956262ef2297ef97.png

原文链接为《MySQL是怎样运行的:从根儿上理解MySQL》小册链接

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

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

相关文章

html绑定带有形参的函数,C++中函数

参数参数分为形参和实参&#xff0c;形参是在函数定义的形参表中进行定义&#xff0c;是一个变量&#xff0c;其作用域为整个函数。而实参出现在函数调用中&#xff0c;是一个表达式&#xff0c;用传递给函数的实参对形参进行初始化。函数形参表可以为空&#xff0c;但不能省略…

ppt里quicktime不可用_十大好看又实用的PPT网站

现在的社会做PPT差不多快成家常便饭了开题报告、毕业答辩、汇报总结、讲课等等但就是找不到好的模板你知道好看又实用的PPT模板要去哪里找吗下面小编就将为大家呈现几款实用的软件及网站其中海量资源&#xff0c;等你发现请跟着小编向下看Top1.PPT美化大师资源广场这是个小软件…

layui 开启关闭标签_欧盟发布照明产品ErP及能效标签法规新草案

欧盟ERP指令从09年发布后经历了多次的标准内容更新&#xff0c;对管控产品的要求也越来越严格。近日&#xff0c;欧洲委员会发布了照明产品ErP及能效标签法规的新草案&#xff0c;旨在取代现行ErP法规EC 244/2009、EC245/2009、EU1194/2012和能效标签法规EU874/2012。新草案里规…

tablets计算机英语,计算机专业英语词汇

下面是秋天网 Qiutian.ZqNF.Com小编为大家带来的计算机专业英语词汇&#xff0c;欢迎大家学习!计算机专业英语词汇&#xff1a;1、parallel port 并行端口parallel port enables microcomputer users to connect to a parallel printer.并行端日使微机用户能与并行打印机相连接…

ae连续流动的线条_贡献 | AE片头制作绝对经验

在视频制作中,AE是必不可少的一款特效制作软件&#xff01;关于AE片头制作&#xff0c;每个人都有自己的一套经验和方法&#xff01;在这里E哥就找到了一篇文章&#xff01;仅供个人制作参考&#xff01;内容如下&#xff1a;1:闪白:通常我不会直接使用白帧叠化,而且在原素材上…

vue 限制渲染条数_深入理解Vue 的条件渲染和列表渲染

这两天学习了Vue.js 感觉条件渲染和列表渲染知识点挺多的&#xff0c;而且很重要&#xff0c;所以&#xff0c;今天添加一点小笔记。条件渲染v-if在 < template > 中配合 v-if 渲染一整组在使用 v-if 控制元素的时候&#xff0c;我们需要将它添加到这个元素上去。然而如果…

此计算机到未能识别网络连接,本地连接显示“未识别的网络”

你好&#xff01;不能上网的原因有很多&#xff1a;1 使用的是mode直接上网还是通过mode再连接路由器上网&#xff1f;如果只是通过mode上网&#xff0c;就是拨号上网&#xff0c;如果不能连接会有提示&#xff0c;直接打电信询问就可以了。(有可能是到mode的线路有问题&…

python打开文件_用Python(in PsychoPy)打开SPSS数据文件

用Python(in PsychoPy)打开SPSS数据文件有时&#xff0c;要访问SPSS的sav文件中的内容&#xff0c;而手里电脑没有SPSS软件&#xff0c;或者需要对SPSS数据文件中的数据进行SPSS支持不够好的操作&#xff0c;如对一组数据反复多次抽样。可以使用Python中的Pandas模块来访问SPSS…

python 操作系统学习_操作系统学习

一、操作系统庄园主——奴隶&#xff0c;找一个管家来传达命令。计算机的世界中叫做操作系统&#xff0c;这个管家就相当于少掉的内存。操作系统帮我们把内容保存到硬盘&#xff0c;帮我们解析指令。二、操作系统都干了什么&#xff1f;接收外部指令转化成0和1。翻译成你写的字…

计算机科学与技术毕业答辩流程,计算机科学与技术学院毕业答辩工作细则

计算机科学与技术学院毕业答辩工作细则为保证毕业生毕业论文答辩的顺利进行&#xff0c;提高毕业答辩质量&#xff0c;现对毕业答辩工作具体操作细节作如下规定&#xff1a;一、答辩论文标准1.论文文题相符、观点明确、论证充分、结论合理、格式规范。2.论文题目变更&#xff0…

iphone黑屏转圈_iphone8一直在黑屏转圈

iPhone8手机开不了机一直在黑屏转圈现象怎么办&#xff1f;一般情况我们会建议手机进行强制重启&#xff0c;但是手机黑屏转圈不开机的故障原因有很多&#xff0c;我们需要一步一步来分析&#xff0c;最后能更有针对性地去解决问题。下面就来和大家说说iphone8一直在黑屏转圈开…

forager有多少个机器人_诠视科技:VSLAM技术进展让移动机器人自主行驶有了更广阔的空间...

图&#xff1a;诠视科技CEO 林琼在移动机器人领域&#xff0c;2018年最大的技术进展莫过于VSLAM技术在该领域的应用突破了&#xff0c;它将让移动机器人自主行驶有更广阔的空间。目前市面上移动机器人自主行驶都是以激光雷达导航为主&#xff0c;双目视觉只是作为辅助使用&…

计算机没有设置无线临时网络,如何创建临时无线网络

1、选择性能高的笔记本做主机在参战笔记本中选一台性能比较高的笔记本做“主在系统右下角的任务栏托盘区中找到网络连接的图标&#xff0c;右键选择“网络和共享中心”。同样的&#xff0c;也可以在Win7的控制面板中进入无线和共享中心&#xff0c;效果是一样的。2、设置无线临…

买电脑主要看什么配置_买笔记本电脑主要看什么? 配置要什么样的才算好?...

买笔记本电脑主要看CPU、显卡、主板、内存、硬盘等硬件的性能参数&#xff0c;当然最关键的是考虑您的使用用途和准备的预算&#xff0c;尽量在预算允许的范围内针对性的选择&#xff0c;不要造成性能的浪费。以下是详细介绍&#xff1a;1、硬件设备的性能是决定电脑优劣的关键…

继电器触点粘连分析_在我们日常电气维护中如何避免由于继电器触点粘连造成的设备故障...

在我们日常电气维护中常常会遇到由于继电器触点粘连而造成的设备动作异常或误动作的情况&#xff0c;尤其是一些运行时间较长的设备&#xff0c;而继电器在我们日常维护检查中很难提前预判到触点是否粘连&#xff0c;而继电器触点异常就会造成设备的动作异常&#xff0c;极易造…

计算基因组学需要计算机知识吗,生物信息学——计算基因组学的一些参考书

有两个都可以在新浪爱问资料Bioinformatics.For.Dummies.2nd.Ed.2007.pdfAn Introductionto Bioinformatics Algorithms.pdf另外看到 Virginia 大学的一些课程The 2012 Computational Genomics Course has been rescheduled toNovember 28 - December 4, 2012用mothur从*.sff进…

神舟笔记本风扇控制软件_十代酷睿+RTX2070加持 高性能游戏本首选神舟战神G9CU7PK...

说起最近的真香游戏本产品&#xff0c;我心中立马浮现出神舟战神G9-CU7PK游戏本&#xff0c;这是一款从基础硬件到整体细节都属于一步到位的高端游戏笔记本。神舟战神G9-CU7PK其最大特点是搭载了NVIDIA GeForce RTX 2070独立显卡&#xff0c;其基于NVIDIA Turing GPU架构&#…

python 读取地震道头数据_【Python】OGR库(1):读取矢量数据

OGR库是一个非常流行的处理地理空间矢量数据的开源库。它可以读取丰富的数据格式&#xff0c;允许用户进行几何处理、属性表操作、数据分析&#xff0c;是个非常强大的开源GIS库。目前OGR已集成在GDAL库中&#xff0c;可以说是GIS的本源之一了&#xff0c;有大量的软件用到了这…

进入其他网络共享计算机,局域网内如何进入其他电脑,两个电脑利用无线建立局域网-...

虽然大家平时都在使用电脑&#xff0c;但是大家中的相当一部分朋友们从来都没想过应该如何通过局域网进入到别人的电脑这个问题。怎么样?听起来是不是很神奇呢?其实这种方法从电脑能狗互联的时候就已经诞生了&#xff0c;只是大家一般不经常使用这种工具&#xff0c;所以就不…

spssχ2检验_卡方检验与单因素logistic回归分析结果比较

在疾病或健康的流行病学研究中,经常需要分析疾病或健康状态与各种影响因素(保护因素或危险因素)的之间的定量关系,由于疾病或健康状态是分类变量,一般采取logistic回归分析。 在做此类数据分析时,对分析疾病或健康状态与单个影响因素之间的关系分析时,直接用卡方检验还是…