MySQL不同隔离级别下的加锁情况

锁的分类

我之前有讲过,锁分为两大类,一是乐观锁,一是悲观锁。这里不再详细讲解。本节主要讲解MySQL在不同的隔离级别情况下,使用的不同粒度的锁机制。

先说明的情况是,无论哪种隔离级别下,如果有索引,加锁都是加在索引上的,只是在不同的隔离级别下,支持的锁粒度不一样而已;锁粒度越小,消耗的资源就越多。如果没有索引,则加锁则是表锁,即锁住聚簇索引中所有行。

隔离级别下的加锁

RR 隔离级别就是,可重复读。REPEATABLE READ。

RC 隔离级别就是,读已提交。READ COMMITTED。

先建表并插入数据,如下。

CREATE TABLE 'blog'(
   'id' BIGINT(20) NOT NULL,
   'name' VARCHAR(16) COLLATE utf8mb4_bin DEFAULT NULL,
   'idcard' BIGINT(20) NOT NULL,
   PRIMARY KEY('id')
) ENGINE=InnoDB DEFAULT CHARSET = utf8mb4 COLLATE=utf8mb4_bin;
-- 插入数据
INSERT INTO blog VALUES(1,'test1',100),(5,'blog',200),(8,'blog',300),(10,'test2',400);

如果是精确匹配,比如根据主键更新。不管是在RR还是在RC隔离级别下,都是会命中聚簇索引上的行锁的,这分为两种情况,如果是以下两种情况,则分别是在行的索引上加X锁和S锁。

//在id=1的聚簇索引上加X锁
UPDATE blog SET name = 'x' WHERE id = 1;
//在id=1的聚簇索引上加S锁
SELECT * FROM blog WHERE id = 1 LOCK IN SHARE MODE;

如果是范围查询,且如果在RC隔离级别下,会在命中的行的聚簇索引上加锁,因为在RC隔离级别下是没有间隙锁的,所以会出现幻读的现象。因为在RR隔离模式下,采用间隙锁解决了幻读问题,所以,如果是在RR隔离模式下,会在所有命中的行的聚簇索引上加next-key locks(锁住行和间隙)。最后命中的索引的后一条记录,也会被加上 next-key lock。

//在RC隔离级别下,在id=8和10的聚簇索引上加X锁
//在RR隔离级别下,在id=8、(10,+)的聚簇索引上加X锁
//在(5,8)(8,10)(10,+)加间隙锁
UPDATE blog SET name = 'test3' WHERE id > 7;
//在RC隔离级别下,在id=1的聚簇索引上加X锁
//在RR隔离级别下,在id=1、5的聚簇索引上加X锁
//在RR隔离级别下,在(-,1)(1,5)加间隙锁
UPDATE blog SET name = 'test4' WHERE id <=1;

如果查找的内容为空,即没有命中聚簇索引,那么,在RC隔离级别下,什么也不会锁,但在RR隔离级别下,会锁住查找目标所在的间隙。

发布了12 篇原创文章 · 获赞 2 · 访问量 669

猜你喜欢

转载自blog.csdn.net/gonghaiyu/article/details/104307527
今日推荐