Mysql 锁的测试

本文目的

1、非唯一索引gap锁的阻塞效果

2、on duplicate key update  死锁问题复现。  mysql 5.7.26 已经修复

一、查看mysql引擎

show engines ;

show variables like '%storage_engine%' ;

show variables like  'innodb_autoinc_lock_mode'  ;

set GLOBAL innodb_status_output_locks=ON;

创建表

CREATE TABLE `user` (

  `ID` int(11) NOT NULL AUTO_INCREMENT,

  `name` varchar(11) COLLATE utf8mb4_bin DEFAULT NULL,

  `COMMENT` varchar(11) CHARACTER SET utf8 DEFAULT NULL,

  PRIMARY KEY (`ID`),

  KEY `user_ix1` (`name`)

) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

插入数据

insert user select 20,20,20;
 
insert user select 25,25,25;
 
insert user select 30,30,30;

-- truncate table user ;

 对比唯一索引和普通索引的处理方式 

ALTER TABLE
    `study`.`user` ADD CONSTRAINT user_ix2 UNIQUE (`name`);
ALTER TABLE
    `study`.`user` ADD CONSTRAINT user_ix3 UNIQUE (`COMMENT`)
ALTER TABLE
    `study`.`user` DROP INDEX `user_ix1`;
ALTER TABLE
    `study`.`user` ADD INDEX user_ix1 (`name`)

查看锁

select * from information_schema.INNODB_LOCKS

间隙锁

--  SESSION 4  用于触发间隙锁
begin;
update user set name = '22' where name='20'
commit ; -- 实验时先不执行commit
rollback ;

 --  SESSION 1 
begin;
insert into  user(id , name , user.comment) value(21,'21','21')  ON DUPLICATE KEY UPDATE comment="s1" 
commit ;  -- 实验时先不执行commit
rollback ;

session4先执行, session1中的sql会被gap锁住,因为name是非唯一索引,name=20 会锁住 (20,25)的索引范围

ONDUPLICATE KEY ON 死锁复现 -- mysql 导致

将name字段改为unique  key 

ALTER TABLE
    `study`.`user` ADD CONSTRAINT user_ix1 UNIQUE (`name`)
--  SESSION 0
begin;
insert into user(name , user.comment) value('22','23')  ON DUPLICATE KEY UPDATE comment="s3" 
commit ;   -- 实验时先不执行commit
rollback ;

--  SESSION 1 
begin;
insert into user(name , user.comment) value('21','21')  ON DUPLICATE KEY UPDATE comment="s1" 
commit ; -- 实验时先不执行commit
rollback ;

 
--  SESSION 2 
begin;
insert into user(name , user.comment) value('21','22')  ON DUPLICATE KEY UPDATE comment="s2" 
commit ; -- 实验时先不执行commit
rollback ;

依次执行 上面3条 insert into .. on duplicate key update  语句, 不要执行commit 或rollcack【这里写出来,只是为了在客户端执行的时候方便】, 

执行完 session 0 , 1 后,可以看到 1被阻塞了

在执行session2

对session 0 执行 commit ;

session 1 ,执行成功 , session2 被干掉了【mysql会解决死锁,就是干掉一个】;

这里面我们看到出现了gap锁,理论上不应该出现这个锁【因为这3条语句都是围绕unique key 搞事情,用也是应该是记录锁,所以这是个bug】

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值