mysql存储引擎innodb隔离级别RR(REPEATABLE READ )锁定读行锁的范围罗列

1.首先创建一个user表

CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1321800983473774597 DEFAULT CHARSET=utf8;

为表中的列name创建一个二级索引

CREATE INDEX name_index ON user (name)

插入五条数据如图所示

id name age email createtime updatetime
1 Jone 18 [email protected]    
3 Tom 150 [email protected]    
4 Mark 23 [email protected]    
5 Lili 18 @cm    
8 olol 66 @161.com    

2.条件列无索引 事务执行锁定读会引发的锁表

锁定读介绍:以下四种类型的语句都是先加各种锁,然后再进行读取。带有update的和DELETE都是排他锁,SELECT ....LOCK IN SHARE MODE就是共享锁(重点)

SELECT ....LOCK IN SHARE MODE
SELECT ...FOR UPDATE;
UPDATE...
DELETE...

我们使用udpate来进行演示

       1.我们先执行事务1

##事务1
begin;##开启事务
update user set age=50 where email='@cm';
 #此处没有用到索引列,必然会走全表扫描
2.1.1执行计划
2.1.2执行之后

注意:此时事务1还没有提交。以下的所有事务1都是未提交状态(就不一一赘述)


   

2.1此时我们执行事务2,id增加插入

  (事务2是个隐式事务 执行完会自动提交事务

##事务2 隐式事务
insert into  user values (9,"boom",'22','ddd',NOW(),NOW());

此时事务2会陷入获取锁的过程而阻塞。阻塞超时后直接报异常

  


  2.2  假设我们执行了事务1后,执行以下语句 事务3

执行了update语句还是锁表

综上2.1和2.2得出一个结论:只要锁定读语句走全表扫描,会进行锁表,更新一条或者多条数据,都会进行锁表,所以应该善用索引




3.锁定读 有索引的情况之一(走唯一索引)

       1.等值查找:锁定读只会加record lock ,不会加gap lock 

        事务1

         

     事务2

            

    此时插入数据是成功的,因为并没有加gap lock,加的是record lock


    2.范围查找:加的是gap lock

事务1

      

     事务2

此时事务2获取锁超时,直接返回异常

         2.1假设我们在事务1开启的情况下,想修改id=5的数据,会发生什么?

      

此时获取成功了。说明等值(唯一索引情况下)加的是record lock

    2.2  假设我们在事务1开启的情况下,想修改id=4的数据,会发生什么?

   

此时id=4的数据修改成功,证明了gap锁,大于5的所有数据 还有锁住查询条件8和5之间的数据


3.锁定读(聚簇索引,二级索引 )

     1.还是和上面的事务1一样,现在我们探讨的是,如果我们使用了update语句修改的列带有索引。那么此时也要将索引锁住,锁住索引的锁用的是record lock。

     事务1

    

事务2.此时我们使用共享锁来读取锁,然后等待锁,超时


    现在我们使用索引范围匹配

事务1   二级索引 按字母进行排序     JLM字母开头这样的顺序

        

事务2     这个共享锁 是以M开头的,肯定中标了

我们再来看以J开头的会不会中标

很明显J开头的并不会中标,符合gap lock

小结一下:索引也是gap锁。但是锁住聚簇索引就使用了record 锁。反之,如果我们在聚簇索引中更改了一条数据,更改的列涉及索引列,那么此时就使用record锁住二级索引

补充:如果有索引下堆,那么可能不用回表,从而不使用record锁锁住聚簇索引的数据

猜你喜欢

转载自blog.csdn.net/zcjluse/article/details/109910184