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美化大师资源广场这是个小软件…

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

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

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

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

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

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

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

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

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

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

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

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

神舟笔记本风扇控制软件_十代酷睿+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;所以就不…

appcrash事件怎么解决_解决问题的最佳办法,是让问题不再是问题

我们常常陷入迷局&#xff0c;绕来绕去却怎么也找不到出路。因为&#xff0c;当事者迷&#xff0c;旁观者清。身在局中&#xff0c;我们的思维很容易就被固定在既定的逻辑里。有的是以往的经验总结&#xff0c;有些是从他人处习得。对于我们已经习得的东西&#xff0c;在遇到事…

台式计算机的硬件组成部分,台式电脑主机的硬件组成部分简介

计算机硬件系统中用于放置主板及其他主要部件的容器(Mainframe)。通常包括 CPU、内存、硬盘、光驱、电源、以及其他输入输出控制器和接口&#xff0c;如 USB 控制器、显卡、网卡、声卡等等。位于主机箱内的通常称为内设&#xff0c;而位于主机箱之外的通常称为外设(如显示器、键…

python 伪造源ip_Swaks伪造邮件

0x00 swaksswaks - Swiss Army Knife SMTP, the all-purpose smtp transaction tester.swaks堪称SMTP协议的瑞士军刀&#xff0c;使用它我们可以灵活的操作SMTP协议报文&#xff0c;这篇文章主要是记录一下我是如何伪造一封邮件绕过gmail的检测。通常最简单的发送命令&#xff…

clientmacaddr进不去系统win10_教你一分钟搞定戴尔电脑WIN10改WIN7

最近有很多人问小编&#xff0c;戴尔的新款电脑WIN10(win8)改WIN7电脑不认U盘&#xff0c;不知道怎么设置&#xff0c;今天小编就给大家分享一个快速进入的方法。首先把装有系统的U盘插入电脑&#xff0c;开机一直按F12进入Bios菜单第二步&#xff1a;进入菜单界面后&#xff0…

win7笔记本外接显示器html,window7笔记本外接显示器只显示一个屏幕怎么设置

许多用户都会偏向于入手win7笔记本电脑&#xff0c;这样电脑携带起来也是非常方便&#xff0c;不过由于屏幕较小的缘故&#xff0c;有用户就会选择外接一台显示器&#xff0c;不过在给win7笔记本外接显示器之后就需要对于其进行设置只显示一个屏幕&#xff0c;接下来小编就来教…

苹果手机怎么查看足迹_用了5年苹果手机!才知道查看一个字母就能辨别手机真假...

苹果手机的价格一般都比较贵&#xff0c;所以大家都怕买到假货&#xff01;今天笔者就教大家如何快速分辨苹果手机真假&#xff0c;只需查看一个字母就能知道手中的苹果手机是什么型号。方法一&#xff1a;桌面图标iPhone手机桌面上的时钟图标比较特别&#xff0c;它的时针会随…

java实现矩阵谱峰搜索算法

矩阵谱峰搜索算法&#xff0c;也称为矩阵谱峰查找算法&#xff0c;是一种用于搜索二维矩阵中谱峰的方法。谱峰是指在矩阵中的一个元素&#xff0c;它比其上下左右四个相邻元素都大或相等。 该算法的基本思想是从矩阵的中间列开始&#xff0c;找到该列中的最大元素&#xff0c;…

电脑中计算机右键管理无法打开,win8系统计算机右键菜单中的管理打不开怎么办...

‍‍计算机管理一组Windows管理工具&#xff0c;这些工具被组合到一个控制台中&#xff0c;方便我们操作。最近有些雨林木风win8旗舰版用户遇到了计算机管理打不开的情况&#xff0c;在右键点击计算机打开菜单后&#xff0c;点击管理打不开&#xff0c;遇到这种问题该怎么办呢&…

中海达gps软件wince_应用|无人机航测15分钟能做啥?中海达PPK告诉你答案

标星置顶&#xff0c;一秒找到中海达讯点击上方“中海达讯”→点击右上角“…”→点选“设为星标 ★”在航测作业中快速现场成图生成快拼成果报告快速通过内方位元素精度评估完成以上步骤你最快要多长时间&#xff1f;15分钟这是中海达PPK套装给出的答案点击视频查看中海达PPK套…