文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

腾讯一面:MySQL的共享锁和独占锁

2024-12-13 14:24

关注

申明:本文基于 MySQL 8.0.30 版本,InnoDB引擎。

一、共享锁

1.什么是共享锁?

共享锁(shared lock,S锁),也叫读锁。它是指当对象被锁定时,允许多个事务同时读取该资源,也允许其它事务从该对象上再次获取共享锁,但不能对该对象进行写操作。

2.加锁方式

共享锁一般通过下面 2种方式进行加锁:

# 方式1
select ... lock in share mode;

# 方式2
select ... for share;

如果事务T1 持有某对象的共享(S)锁,则事务T2 需要再次获取该对象的锁时,会出现下面两种情况:

二、举例说明

为了更好地理解上述两种情况,这里分别以下面的执行顺序流对InnoDB存储引擎和MyISAM存储引擎进行验证:

1.InnoDB存储引擎

创建一张用户user表,表结构如下:

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

(1) 给行加共享锁

这里给user表中id=3行加共享锁为例,执行顺序流如下表:

加锁线程  sessionA

线程B  sessionB

线程C  sessionC

#开启事务

begin;



#给id=3的行加共享锁

select * from user

where id = 3 lock in share mode;




#获取id=3行的共享锁成功

#select操作执行成功

select * from user where id=3;

#获取id=3行的共享锁成功

#select操作执行成功

select * from user where id=3;


#获取id=3行的排它锁失败

#delete操作被堵塞

delete from user where id = 3;

#获取id=4行的排它锁成功

#delete操作执行成功

delete from user where id = 4;

#提交事务

#id=3的行上共享锁被释放

commit;




#获取id=3行的排它锁成功

#被堵塞的delete操作执行成功

delete from user where id = 3;


示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)对user中id=3这行添加共享锁后,事务B(sessionB)和事务C(sessionC)都可以获取user表的共享锁,也就是select操作能成功执行,但是事务B(SessionB)获取user表id=3的写锁失败,即delete where id=3操作被阻塞,而事务C(sessionC)获取user表id=4的写锁成功,即delete where id=4操作成功;

(2) 给表加共享锁

这里通过lock in share mode方式给user整张表添加共享锁,执行顺序流如下表:

加锁线程   sessionA

线程B    sessionB

#开启事务

begin;


#对user整张表加共享锁

select * from user lock in share mode;



#成功获取user表的共享锁,select操作成功执行

select * from user;


#获取user表的排他锁失败,操作被堵塞

delete from user where id = 1;

#提交事务

#user表的共享锁被释放

commit;



#获取user表上排他锁成功,delete操作执行成功

delete from user where id = 1;

示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)对user整张表添加共享锁后,事务B(sessionB)可以获取user表的共享锁,也就是select操作能成功执行,但是事务B(SessionB)获取user表的写锁失败,即delete操作被阻塞。

所以,尽管共享锁(S锁)是InnoDB存储引擎的行级别锁,但是一旦它作用到整张表时,其实是对表中所有的行加共享锁。

2.MyISAM引擎

创建一张用户person表,表结构如下:

CREATE TABLE `person` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_name` (`name`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_

给行加共享锁

这里给person表的id=3行加共享锁为例,执行顺序流如下表:

加锁线程  sessionA

线程B  sessionB

#开启事务

begin;


#给id=3的行加共享锁

select * from person where id = 3 lock in share mode;



#获取id=3行的共享锁成功

#select操作成功

select * from person where id=3;


#获取id=3行的排它锁成功

#update操作成功

update person set name='name3xx' user where id = 3;


select * from person where id=3;

#提交事务

#id=3行上共享锁被释放

commit;


示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)对person中id=3这行添加共享锁后,事务B(sessionB)既能获取person表的共享锁,也能获取person表id=3的写锁,即select和update where id=3都操作成功;

因此,在MyISAM引擎中其实不存在共享锁。

3.总结

通过上述示例及其运行结果可以看出:

共享锁是InnoDB存储引擎的行级锁,在MyISAM存储引擎中不存在;

共享锁是尽管是行级别锁,但是当锁加在整个表时(表中所有的行,一种特殊的行),排他锁也会在表级别生效;

三、排它锁

1.什么是排他锁?

排它锁(exclusive lock,X锁),也叫写锁或者独占锁,主要是防止其它事务和当前加锁事务锁定同一对象,同一对象主要有两层含义:

2.加锁方式

排他锁加锁的方式一般有 2种:显式加锁和隐式加锁,如下:

-- 显式加锁
select ... for update;

-- 隐式加锁,是 MySQL内部自动加锁

为了更好的说明排他锁,这里以下面的执行顺序流来进行验证,用户user表的结构还是和上面的一样:

四、举例说明

为了更好地理解上述两种情况,这里分别以下面的执行顺序流对InnoDB存储引擎和MyISAM存储引擎进行验证:

1.InnoDB存储引擎

(1) 给行加排他锁

这里通过for update显式给user表中id=6行加排他锁为例,执行顺序流如下表:

加锁线程  sessionA

线程B  sessionB

线程C  sessionC

#开启事务

begin;



#给id=6的行加排他锁

select * from user

where id = 6 for update;




#获取id=6的共享锁成功

select * from user where id=6;

#获取id=6的共享锁成功

select * from user where id=6;


#获取id=6的排它锁失败

delete from user where id = 6;

#获取id=7的排它锁成功

delete from user where id = 7;

#提交事务

#user表id=6的行上排他锁被释放

commit;




#获取id=6的排它锁成功

#被堵塞的delete操作执行成功

delete from user where id = 6;


示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)对user中id=6这行添加共享锁后,事务B(sessionB)和事务C(sessionC)都可以获取user表的共享锁,也就是select操作能成功执行,但是事务B(SessionB)获取user表id=6的写锁失败,即delete where id=6操作被阻塞,而事务C(sessionC)获取user表id=7的写锁成功,即delete where id=7操作成功;

(2) 给表加排他锁

这里通过for update显式方式给user整张表添加排他锁,执行顺序流如下表:

加锁线程   sessionA

线程B    sessionB

#开启事务 begin;


#对user整张表加排他锁

select * from user for update;



#获取user表上的共享锁成功,select执行成功

select * from user;


#获取user表上的排他锁失败,操作被堵塞

delete from user where id=3;

#提交事务

#user表上的排他被释放

commit;



#获取user表上的排他锁成功,操作执行成功

delete from user where id = 3;

示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)对user整张表加排他锁后,事务B(sessionB)可以获取user表的共享锁,也就是select操作能成功执行,但是事务B(SessionB)获取user表的排他锁失败,即delete操作被阻塞;

所以,尽管排他锁(X锁)是InnoDB存储引擎的行级别锁,但是一旦它作用到整张表时,其实是对表中所有的行加排他锁。

2.MySQL 隐式加排他锁

这里通过MySQL隐式给user的id=6行添加排他锁,执行顺序流如下表

加锁线程   sessionA

线程B    sessionB

#开启事务 begin;


#MySQL隐式给id=6行加排他锁

update user set name = 'name6' where id =6;



#获取id=6的共享锁失败,select执行被阻塞

select * from user where id = 6 lock in share mode;

#提交事务

#id=6的排他被释放

commit;



#获取id=6表上的共享锁成功,select执行成功;

示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)执行update where id=6时,MySQL会隐式加排他锁,事务B(sessionB)在lock in share mode模式下获取user表id=6的共享锁失败,也就是select操作能成功被阻塞;

3.MyISAM引擎

MySQL 隐式加排他锁

这里通过MySQL隐式给person的id=4行添加排他锁,执行顺序流如下表:

加锁线程   sessionA

线程B    sessionB

#开启事务 begin;


#MySQL不会隐式给id=4行加排他锁

update person set name = 'name4' where id =4;



#获取id=4的共享锁成功,select执行成功

select * from user where id=4 lock in share mode;


#获取id=4表上的共享锁成功,select执行成功;

#提交事务 id=4的排他被释放

commit;


示例执行结果图如下:

通过上述的示例执行结果可以看出:当事务A(sessionA)执行update where id=6时,MySQL不会隐式加排他锁,事务B(sessionB)既能获取id=4的共享锁,也能获取id=4的排他锁;

因此,在MyISAM引擎中其实不存在排他锁。

4.总结

通过上述 3个示例及其运行结果可以看出:排他锁有表级别共享锁和行级别共享锁和自动锁机制 3种 表级别共享锁:

五、共享锁和排他锁的兼容性矩阵

为了更好地理解共享锁和排他锁的互斥关系,可以参考以下兼容性矩阵:


无锁

共享锁

排他锁

无锁

允许

允许

允许

共享锁

允许

允许

阻塞

排他锁

允许

阻塞

阻塞

从上述矩阵可以看出:

六、总结

来源:猿java内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯