从一个案例深入剖析InnoDB隐式锁和可见性判断(2)

简介: 从一个案例深入剖析InnoDB隐式锁和可见性判断
4、关于page的max trx id

我们上面多次提到二级索引page的max trx id,这个max trx id实际就是PAGE_MAX_TRX_ID,它位于page的offset 56后的8个字节,实际上这个值只会存在于二级索引上,主键没有这个值,我们可以看到如下:

表结构和数据
mysql> show create table testimp4 \G
*************************** 1. row ***************************
       Table: testimp4
Create Table: CREATE TABLE `testimp4` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `d` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `b` (`b`),
  KEY `d` (`d`)
) ENGINE=InnoDB AUTO_INCREMENT=10000 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select *from testimp4;
+------+------+------+------------------------------------+
| id   | a    | b    | d                                  |
+------+------+------+------------------------------------+
|    5 |    5 |  300 | NULL                               |
|    6 | 7000 | 7700 | 1124                               |
|   11 | 7000 | 7700 | 1124                               |
|   12 | 7000 | 7700 | 1124                               |
|   13 | 2900 | 1800 | NULL                               |
|   14 | 2900 | 1800 | NULL                               |
| 1000 |   88 | 1499 | NULL                               |
| 4000 | 6000 | 5904 | iiiafsafasfihhhccccchhhigggofgo111 |
| 4001 | 7000 | 7700 | 1124454555                         |
| 9999 | 9999 | 9999 | a                                  |
+------+------+------+------------------------------------+
10 rows in set (0.00 sec)

每次每行更新后会更新这个值,如果大于则修改,小于则不变。函数page_update_max_trx_id中有如下片段

begin;insert into testimp4 values(10000,10000,10000,'gp');(不提交)

四、关于加锁的阶段

我们一般锁需要加锁的都是DML语句和select for update这样的语句,这里将加锁分为数据查找和数据修改两个阶段。

  • 对于select for update:

主键访问数据:访问主键判断是否存在隐式锁,然后加显示锁。二级索引访问数据(需要回表的情况):访问二级索引判断是否存在隐式锁,然后加显示锁,接着回表主键判断是否存在隐式锁,然后加显示锁。

  • 对于update/delete:

主键访问修改数据:数据查找阶段主键判断是否存在隐式锁,然后加显示锁。数据修改阶段涉及到了其他二级索引,那么维护相应的二级索引加隐含锁。

二级索引访问修改数据:数据查找阶段二级索引判断是否存在隐式锁(可能需要回表判断),二级索引加显示锁,数据修改阶段回表修改主键数据加显示锁,然后维护各个二级索引(修改字段涉及的二级索引或者修改主键则包含全部二级索引)加隐式锁。

  • 对于insert而言如果没有堵塞(插入印象锁和gap lock堵塞),那么始终为隐式锁。

注意这里我们看到了隐式锁,隐式锁不会占用row的结构体,因此在show engine innodb status里面是看不到的,除非有其他事务显示将其转换为显示锁。我们来做几个例子如下(REPEATABLE READ隔离级别):

4.1 插入数据
begin;insert into testimp4 values(10000,10000,10000,'gp');(不提交)


image.png

# T1时刻S1锁状态:

---TRANSACTION 94487, ACTIVE 5 sec
1 lock struct(s), heap size 1160, 0 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 482 localhost root starting
show engine innodb status
TABLE LOCK table `test`.`testimp4` trx id 94487 lock mode IX

# T2时刻S1锁状态:
---TRANSACTION 94487, ACTIVE 271 sec
2 lock struct(s), heap size 1160, 1 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 484 localhost root starting
show engine innodb status
TABLE LOCK table `test`.`testimp4` trx id 94487 lock mode IX
RECORD LOCKS space id 501 page no 3 n bits 80 index PRIMARY of table `test`.`testimp4` trx id 94487 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 4; hex 80002710; asc ' ;;
1: len 6; hex 000000017117; asc q ;;
2: len 7; hex d0000002c40110; asc ;;
3: len 4; hex 80002710; asc ' ;;
4: len 4; hex 80002710; asc ' ;;
5: len 2; hex 6770; asc gp;;

# T3时刻S1锁状态:
---TRANSACTION 94487, ACTIVE 337 sec
3 lock struct(s), heap size 1160, 2 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 521 localhost root starting
show engine innodb status
TABLE LOCK table `test`.`testimp4` trx id 94487 lock mode IX
RECORD LOCKS space id 501 page no 3 n bits 80 index PRIMARY of table `test`.`testimp4` trx id 94487 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 4; hex 80002710; asc ' ;;
1: len 6; hex 000000017117; asc q ;;
2: len 7; hex d0000002c40110; asc ;;
3: len 4; hex 80002710; asc ' ;;
4: len 4; hex 80002710; asc ' ;;
5: len 2; hex 6770; asc gp;;

RECORD LOCKS space id 501 page no 4 n bits 80 index b of table `test`.`testimp4` trx id 94487 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 80002710; asc ' ;;
1: len 4; hex 80002710; asc ' ;;

# T4时刻S1锁状态:
---TRANSACTION 94487, ACTIVE 408 sec
4 lock struct(s), heap size 1160, 3 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 559 localhost root starting
show engine innodb status
TABLE LOCK table `test`.`testimp4` trx id 94487 lock mode IX
RECORD LOCKS space id 501 page no 3 n bits 80 index PRIMARY of table `test`.`testimp4` trx id 94487 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 4; hex 80002710; asc ' ;;
1: len 6; hex 000000017117; asc q ;;
2: len 7; hex d0000002c40110; asc ;;
3: len 4; hex 80002710; asc ' ;;
4: len 4; hex 80002710; asc ' ;;
5: len 2; hex 6770; asc gp;;

RECORD LOCKS space id 501 page no 4 n bits 80 index b of table `test`.`testimp4` trx id 94487 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 80002710; asc ' ;;
1: len 4; hex 80002710; asc ' ;;

RECORD LOCKS space id 501 page no 5 n bits 80 index d of table `test`.`testimp4` trx id 94487 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 2; hex 6770; asc gp;;
1: len 4; hex 80002710; asc ' ;;

实际上我们看到这里insert语句后主键和各个索引都上了隐含锁只是看不到,通过其他S2,S3,S4我们逐步把这些隐式锁转换为了显示锁。

4.2 delete语句通过主键删除数据

image.png

# T1时刻S1锁状态:
---TRANSACTION 94493, ACTIVE 3 sec
2 lock struct(s), heap size 1160, 1 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 567 localhost root
TABLE LOCK table `test`.`testimp4` trx id 94493 lock mode IX
RECORD LOCKS space id 501 page no 3 n bits 80 index PRIMARY of table `test`.`testimp4` trx id 94493 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 6; compact format; info bits 32
0: len 4; hex 8000270f; asc ' ;;
1: len 6; hex 00000001711d; asc q ;;
2: len 7; hex 550000003b071b; asc U ; ;;
3: len 4; hex 8000270f; asc ' ;;
4: len 4; hex 8000270f; asc ' ;;
5: len 1; hex 61; asc a;;

# T2时刻S1锁状态:
---TRANSACTION 94493, ACTIVE 112 sec
4 lock struct(s), heap size 1160, 3 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 567 localhost root
TABLE LOCK table `test`.`testimp4` trx id 94493 lock mode IX
RECORD LOCKS space id 501 page no 3 n bits 80 index PRIMARY of table `test`.`testimp4` trx id 94493 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 6; compact format; info bits 32
0: len 4; hex 8000270f; asc ' ;;
1: len 6; hex 00000001711d; asc q ;;
2: len 7; hex 550000003b071b; asc U ; ;;
3: len 4; hex 8000270f; asc ' ;;
4: len 4; hex 8000270f; asc ' ;;
5: len 1; hex 61; asc a;;

RECORD LOCKS space id 501 page no 4 n bits 80 index b of table `test`.`testimp4` trx id 94493 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 8000270f; asc ' ;;
1: len 4; hex 8000270f; asc ' ;;

# T3时刻S1锁状态:
---TRANSACTION 94493, ACTIVE 133 sec
4 lock struct(s), heap size 1160, 3 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 140737089492736, query id 567 localhost root
TABLE LOCK table `test`.`testimp4` trx id 94493 lock mode IX
RECORD LOCKS space id 501 page no 3 n bits 80 index PRIMARY of table `test`.`testimp4` trx id 94493 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 6; compact format; info bits 32
0: len 4; hex 8000270f; asc ' ;;
1: len 6; hex 00000001711d; asc q ;;
2: len 7; hex 550000003b071b; asc U ; ;;
3: len 4; hex 8000270f; asc ' ;;
4: len 4; hex 8000270f; asc ' ;;
5: len 1; hex 61; asc a;;

RECORD LOCKS space id 501 page no 4 n bits 80 index b of table `test`.`testimp4` trx id 94493 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 8000270f; asc ' ;;
1: len 4; hex 8000270f; asc ' ;;

RECORD LOCKS space id 501 page no 5 n bits 80 index d of table `test`.`testimp4` trx id 94493 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 1; hex 61; asc a;;
1: len 4; hex 8000270f; asc ' ;;


实际上我们看到这里delete语句后,主键加了显示锁,这是因为数据查找阶段需要加显示锁,但是各个二级索引是由于维护而加的是隐式锁,我们通过S2,S3将其转换为了显示锁。

            </div>
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
Android开发 数据安全/隐私保护
Android TextView 使用以及属性(方法)大全(下)
TextViewXML属性和相关方法说明(2)
1450 0
|
API 开发工具 虚拟化
pyVmomi操作VMware
pyVmomi操作VMware
2084 0
|
运维 Ubuntu JavaScript
【Linux | 学习路线分享】
【Linux | 学习路线分享】
373 0
【Linux | 学习路线分享】
|
数据挖掘
数据分析八大模型:详解RFM模型
今天跟大家分享的是一个经常被提及,但是价值被严重低估的模型:RFM模型。
2132 1
数据分析八大模型:详解RFM模型
|
弹性计算 前端开发 安全
阿里云服务器宝塔面板部署项目
本文章讲解宝塔面板的安装与宝塔面板前后端项目的部署
1091 0
阿里云服务器宝塔面板部署项目
|
Web App开发 存储 编解码
ICO图标的制作和实际应用场景
什么是ICO图标 favicon,即Favorites Icon的缩写,是指显示在浏览器收藏夹、地址栏和标签标题前面的个性化图标。 以图标的方式区别不同的网站。
ICO图标的制作和实际应用场景
|
安全 网络协议 网络安全
3分钟搞定从申请ssl证书到域名服务器配置
3分钟搞定从申请ssl证书到域名服务器配置
872 0
3分钟搞定从申请ssl证书到域名服务器配置
|
运维
云上系统应该在什么地方进行定级备案?
云上系统应该在什么地方进行定级备案?
296 0
|
定位技术 Python
元旦C位出道,用微信好友头像拼个中国地图吧!
准备用好友头像拼接成背景图,用中间透明的中国地图加以覆盖,即可生成一个酷炫的照片地图。
2115 0
元旦C位出道,用微信好友头像拼个中国地图吧!