首页 > 数据库 >【MySQL】InnoDB中的GAP锁详解

【MySQL】InnoDB中的GAP锁详解

时间:2023-04-23 10:37:12浏览次数:33  
标签:insert 19 lock update GAP InnoDB MySQL test where


测试数据:

CREATE TABLE `lock_test` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) NOT NULL,
  `c` int(11) NOT NULL,
  `d` int(11) NOT NULL,
  PRIMARY KEY (`a`),
  UNIQUE KEY `idx_b` (`b`),
  KEY `idx_c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `lock_test` (`a`, `b`, `c`, `d`) VALUES (10, 1, 1, 1);
INSERT INTO `lock_test` (`a`, `b`, `c`, `d`) VALUES (20, 3, 4, 5);
INSERT INTO `lock_test` (`a`, `b`, `c`, `d`) VALUES (30, 6, 8, 10);
INSERT INTO `lock_test` (`a`, `b`, `c`, `d`) VALUES (40, 9, 12, 15);

主键索引-等值查询-键存在

T1

T2

begin;

select * from lock_test where a=10 for update;

begin;

select * from lock_test where a=10 for update; – 阻塞

insert into lock_test values(19, 19, 1, 1); – 成功

update lock_test set b=1 where a=10; – 阻塞

rollback;

结论:T1对a=10的数据加了记录锁,记录锁与记录锁互斥。

主键索引-等值查询-键不存在

T1

T2

begin;

select * from lock_test where a=15 for update;

begin;

select * from lock_test where a=15 for update; – 成功

insert into lock_test values(19, 19, 1, 1); # 阻塞

update lock_test set b=1 where a=10; # 成功

rollback;

结论:T1对a为(10,20)的区间加了GAP锁,GAP锁与GAP锁之间不互斥。

唯一索引-等值查询-键存在

T1

T2

begin;

select * from lock_test where b=3 for update;

begin;

insert into lock_test values(19, 4, 1, 1); – 成功

update lock_test set c=4 where b=3; – 阻塞

rollback;

结论:T1对b=3的数据加了记录锁。

唯一索引-等值查询-键不存在

T1

T2

begin;

select * from lock_test where b=5 for update;

begin;

insert into lock_test values(19, 4, 1, 1); – 阻塞

update lock_test set c=4 where b=3; – 成功

rollback;

结论:T1对b为(3,6)的区间加了GAP锁。

普通索引-等值查询-键存在

T1

T2

begin;

select * from lock_test where c=4 for update;

begin;

insert into lock_test values(19, 42, 5, 1); – 阻塞

update lock_test set b=3 where c=4; – 阻塞

rollback;

结论:T1对c为(1,8)的区间数据加了GAP锁。

普通索引-等值查询-键不存在

T1

T2

begin;

select * from lock_test where c=6 for update;

begin;

insert into lock_test values(19, 42, 5, 1); – 阻塞

update lock_test set b=3 where c=4; – 成功

rollback;

结论:T1对c为(4,8)的区间数据加了GAP锁。

唯一索引-范围查询

T1

T2

begin;

select * from lock_test where a>=10 and a<15 for update;

begin;

insert into lock_test values(19, 42, 5, 1); – 阻塞

update lock_test set b=3 where a=20; – 阻塞

rollback;

结论:T1对a为[10,20]的区间数据加了next-key锁。

普通索引-范围查询

T1

T2

begin;

select * from lock_test where c>=8 and c<10 for update;

begin;

insert into lock_test values(19, 42, 7, 1); – 阻塞

insert into lock_test values(19, 42, 11, 1); – 阻塞

rollback;

结论:T1对c为(4,12]的区间数据加了next-key锁。

普通索引-limit

T1

T2

begin;

select * from lock_test where c=8 limit 1 for update;

begin;

insert into lock_test values(19, 42, 7, 1); – 阻塞

insert into lock_test values(19, 42, 11, 1); – 成功

rollback;

结论:T1对c为(4,8]的区间数据加了next-key锁。

无索引

T1

T2

begin;

select * from lock_test where d=10 for update;

begin;

insert into lock_test values(19, 42, 7, 1); – 阻塞

insert into lock_test values(19, 42, 11, 100); – 阻塞

rollback;

结论:T1对整个表都加了锁。

总结

  • 等值查询:针对唯一索引,如果该记录不存在,会产生间隙锁,如果记录存在,则只会产生记录锁;而普通索引会产生间隙锁
  • 对于查找某一范围内的查询语句,不管什么索引都会产生next-key锁,普通索引可以使用limit减少锁区间范围。
  • 如果列上无索引会导致锁表。


标签:insert,19,lock,update,GAP,InnoDB,MySQL,test,where
From: https://blog.51cto.com/u_6784072/6216457

相关文章

  • InnoDB之Undo log
    事务回滚的需求事务需要保证原子性,也就是事务中的操作要么全部完成,要么什么也不做。但是偏偏有时候事务执行到一半会出现一些情况,比如:1、事务执行过程中可能遇到各种错误,比如服务器本身的错误,操作系统错误,甚至是突然断电导致的错误。2、程序员可以在事务执行过程中手动输入ROLLBACK......
  • MySQL数据类型之日期型
    日期类型日期类型占用空间(字节数)表示范围date41000-01-01~9999-12-31datetime81000-01-0100:00:00.000000~9999-12-3123:59:59.999999timestamp41970-01-0100:00:00.000000UTC~2038-01-1903:14:07.000000UTCyear11901-2155time3-838:59:59.000000~838:59:59.000000date......
  • 16.InnoDB Cluster 简单搭建
    1.主机规划列表、iphostname主机角色安装软件192.168.10.134db01mastermysql、myshell192.168.10.130db02slavemysql、myshell192.168.10.131db03slavemysql、myshell192.168.10.132db04managermyshell、myrouter      2.......
  • 【IT老齐002】MySQL集群模式与应用场景
    【IT老齐002】MySQL集群模式与应用场景单库模式优点简单粗暴适合数据量干万以下小型应用企业网站,创业公司首选缺点不具备可用性与并发性读写分离集群模式读写分离中间件insert、update、delete负载均衡到从库select路由到主库MySQL主从复制binlog......
  • Mysql解决Authentication plugin ‘caching_sha2_password‘ cannot be loaded
    1、登录Mysqlmysql-uroot-p2、修改账户密码加密规则并更新用户密码//修改加密规则ALTERUSER'root'@'localhost'IDENTIFIEDBY'password'PASSWORDEXPIRENEVER;//更新一下用户的密码ALTERUSER'root'@'localhost'IDENTIFIEDWITHmysql_native_pa......
  • archlinux安装配置MySQL8.x版本
    一:到官网下载Community版本的MySQL:https://dev.mysql.com/downloads/mysql/ 二:解压下载的mysql:xz-dmysql-8.0.33-linux-glibc2.17-x86_64-minimal.tar.xz先将.xz文件解压成tar文件,然后再用:tarxvfmysql-8.0.33-linux-glibc2.17-x86_64-minimal.tar将.tar文件解压出来;......
  • mysql设置允许外部访问
    配置mysql允许外部进行登录访问;登录进入mysql;mysql-uroot-p输入密码进入,usermysql;selecthost,userfromuser; 3.更新user表中root用户域属性,’%'表示允许外部访问updateusersethost='%'whereuser='root'; 4.执行以上语句之后再执行:FLUSHPRIVILEGES; ......
  • Docker安装MySQL
    创建挂载目录mkdir-p/app/mysql&&cd$_docker安装MySQLdockerrun-d-p3306:3306--privileged=true-v/app/mysql/log:/var/log/mysql-v/app/mysql/data:/var/lib/mysql-v/app/mysql/conf:/etc/mysql/conf.d-eMYSQL_ROOT_PASSWORD=123456--namemysql5.7......
  • Mysql Mybatis 批量修改数据
    MysqlMybatis批量修改数据MapperIntegerupdateListPO(List<ProjectQuotationItemPO>upateList);方法一:<updateid="updateListPO"><foreachcollection="list"separator=";"item="item">UPDATEpro......
  • Loading class `com.mysql.jdbc.Driver'. 问题
     解决Loadingclass`com.mysql.jdbc.Driver'.Thisisdeprecated.Thenewdriverclassis`com.mysql.cj.jdbc.Driver'.ThedriverisautomaticallyregisteredviatheSPIandmanualloadingofthedriverclassisgenerallyunnecessary.警告问题错误提示:Loadi......