MySQL InnoDB中的锁

您所在的位置:网站首页 mysql如何使用行锁 MySQL InnoDB中的锁

MySQL InnoDB中的锁

#MySQL InnoDB中的锁| 来源: 网络整理| 查看: 265

锁列表 共享与列排他锁意向锁记录锁间隙锁Next-Key锁插入意向锁AUTO-INC锁

这次我们只来讨论和实验意向锁。

Next-Key锁 概述

Next-Key锁称为临键锁。 临键锁可以理解为锁住的是索引本身以及索引之前的间隙,是一个左开右闭的区间。当 SQL 执行按照非唯一索引进行数据的检索时,会给匹配到行上加上临键锁。

锁定区间

在这里插入图片描述

实验

以下实验基于MySQL 8.0.x版本。 建表语句:

CREATE TABLE `sys_user` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '姓名', `name_pinyin` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '姓名拼音', `id_card` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '身份证号', `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '手机号', `age` int(11) NOT NULL DEFAULT 1 COMMENT '年龄', PRIMARY KEY (`id`), UNIQUE KEY `uni_idx_id_card` (`id_card`) USING BTREE COMMENT '唯一索引-身份证号', KEY `idx_phone_name` (`phone`,`name`) USING BTREE COMMENT '普通索引-手机号', KEY `idx_age` (`age`) USING BTREE COMMENT '普通索引-年龄' ) ENGINE=InnoDB AUTO_INCREMENT=3495 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户'

插入记录

insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (1, '小六', 'xiaoliu', 300000000, 13000008000, 10); insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (2, '小六', 'xiaoliu', 300000001, 13000008000, 11); insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (3, '小六', 'xiaoliu', 300000002, 13000008000, 13); insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (4, '小六', 'xiaoliu', 300000003, 13000008000, 20);

记录键存在的间隙区间:

(负无穷大,10](10, 11](11, 13](13, 20](20, 正无穷大] 临键锁区间 (负无穷大,10] 间隙锁范围内插入 事务A: begin; select * from sys_user where age=10 for update;

事务B:

begin; insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (5, '小六', 'xiaoliu', 300000004, 13000008000, 9);

结果: 事务B被阻塞,无法被插入。

间隙锁范围外插入 事务A: begin; select * from sys_user where age=10 for update;

事务B:

begin; insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (5, '小六', 'xiaoliu', 300000004, 13000008000, 11);

结果: 事务B正常插入,无阻塞。

(11, 13]~(13, 20) 间隙锁范围内插入,被阻塞 事务A: begin; select * from sys_user where age=13 for update;

事务B:

begin; insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (6, '小六', 'xiaoliu', 300000005, 13000008000, 12);

结果: 事务B无法正常插入,被阻塞。

间隙锁范围外插入,无阻塞正常插入 事务A: begin; select * from sys_user where age=13 for update;

事务B:

begin; insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (67, '小六', 'xiaoliu', 300000006, 13000008000, 10);

结果: 事务B正常插入。 3. (20, 正无穷大]

间隙锁范围内插入被阻塞 事务A: begin; select * from sys_user where age=20 for update;

事务B:

begin; // 以下两条都会阻塞 insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (67, '小六', 'xiaoliu', 300000006, 13000008000, 13); insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (67, '小六', 'xiaoliu', 300000006, 13000008000, 100000);

结果: 事务B被阻塞。

间隙锁范围外正常插入 事务A: begin; select * from sys_user where age=20 for update;

事务B:

begin; insert into sys_user (id, name, name_pinyin, id_card, phone, age)values (67, '小六', 'xiaoliu', 300000006, 13000008000, 12);

结果: 事务B正常插入。

注意 建议尽可能让所有的查询都使用主键或者唯一索引,这样可以避免临键锁,预防对记录大面积的锁。 参考 https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-record-lockshttps://www.infoq.cn/article/zau0ewzsdtx9zofr6c8whttps://zhuanlan.zhihu.com/p/48269420


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3