您当前的位置: 首页 >  java晴天过后 sql

Mysql学习笔记-临键锁实验

java晴天过后 发布时间:2022-05-24 19:59:51 ,浏览量:4

前言
昨天同事跟我聊到一个问题:InnoDB里面间隙锁锁住的数据可以update么?我们经常都说间隙锁是InnoDB在RR隔离级别下防止幻读的一种处理手段。它可以防止数据在间隙范围中insert数据,但是对于update?很多资料都没有明显说明,今天咱们就通过几个实验来揭开间隙锁的神秘面纱。

0|1mysql命令

  • 查看自动提交事务开关状态:show variables like 'autocommit';
  • 关闭自动事务:set autocommit = 0;
  • 查看事务隔离级别:show variables like 'transaction%';
  • 设置事务隔离级别:set session transaction isolation level read committed;
  • 查看当前服务器锁情况:select * from performance_schema.data_locks;

0|2环境

Mysql Server 8.0.28 / InnoDB / RR

0|3实验表

CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `card` varchar(18) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  `sex` int DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

初始化数据

下面让我们开启实验

1|0实验一:foru update查询下,主键更新

sql

-- 事务一:主键写锁查询,左开右开
select * from user where id > 3 and id < 8 for update;
-- 事务二:范围内更新,根据主键更新值
update user set name = 1 where id = 7;

实验结果(锁冲突等待)

结果分析:

红框部分为更新事务,持有IX锁,等待行锁获取,行锁加锁对象为主键索引7;非红框部分为查询事务,范围内记录均持有X锁(临键锁),锁定的都是LOCK_DATA值前面的间隙和值本身,但是主键索引为8的数据,不包含本身。

示意图如下

ps:
x:间隙锁(左开右闭),即临键锁
x,GAP:间隙锁(双端开口)
X,REC_NOT_GAP:记录锁即行锁

2|0实验二:foru update查询下,不使用索引

sql

-- 事务一:非索引写锁查询,左开右闭
select * from user where age > 18 and age  '0002' and card             
关注
打赏
查看更多评论