深入学习mysql(二)

mysql锁


一、锁的简介

在这里插入图片描述

1.锁的概念

锁是计算机协调多个进程或线程并发访问某一资源的机制。

在数据库中,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。

锁对数据库而言显得尤其重要,也更加复杂。

二、MyISAM的表锁

mysql的表级锁有两种模式: 表共享读锁 和 表独占写锁

1.理解读锁和写锁

首先我们创建一张存储引擎为myisam的表并往表中插入几条数据

create table testmysam(
	id int PRIMARY key
)ENGINE=myisam

insert into testmysam values (1),(2),(3)

然后给testmysam加读锁

lock table testmysam READ

如果在当前session中继续进行插入操作,则报错

insert into testmysam values(2)

在这里插入图片描述

进行更新操作,也报错

update testmysam set id = 6 where id  = 1

在这里插入图片描述

结论: 对MyISAM表的读操作,不会阻塞当前session对表读,当对表进行修改会报错

我们不禁会思考,既然同一个会话不行,那么如果在另一个会话中进行新增操作呢
在这里插入图片描述
我们发现此时在另一个会话没有报错,而是进入了等待操作
如果在另一个会话是读操作呢
在这里插入图片描述
发现也是可以的,当然,在当前session中查询也是没有问题的

总结:对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求

再回过头来看进行锁操作的会话,如果进行对testmysam 所在数据库下的其他表进行新增操作会如何?你觉得能操作成功吗?

在这里插入图片描述

结果是报错

那么对其他表新增不行,查询可以吗?

在这里插入图片描述
结果还是报错

但如果我们在另一个会话中插入则可以成功

在这里插入图片描述

总结:一个session使用LOCK TABLE命令给表f加了读锁,这个session可以查询锁定表中的记录,但更新或访问其他表都会提示错误;

上面我们对读锁进行了分析,先使用 unlock TABLES释放下锁,然后接下来我们再看看写锁

lock table testmysam WRITE

在这里插入图片描述
我们发现在同一个session中进行新增,编辑和删除和查询都是可以的
但是此时入果查询其他表
在这里插入图片描述
可以发现报错了

结论:对 MyISAM表的写操作,当前session可以对本表做CRUD,但对其他表进行操作会报错
此时如果在另一个会话中进行查询操作
在这里插入图片描述
我们发现进入了等待状态

总结:对 MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;

三.InnoDb行锁

行锁:

共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。

排它锁又称:写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。

注意:

1.两个事务不能锁同一个索引。
2.insert ,delete , update在事务中都会自动默认加上排它锁。
3.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。

首先我们创建一张表,注意c2加了索引,而c1没加

CREATE TABLE testdemo ( 
`id` int(255) NOT NULL ,
`c1` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,   `c2` int(50) NULL DEFAULT NULL ,
 PRIMARY KEY (`id`), 
 INDEX `idx_c2` (`c2`) USING BTREE 
 )
 ENGINE=InnoDB; 

插入数据

insert into testdemo VALUES(1,'1',1),(2,'2',2);

begin开启一个事务,然后查询testdemo表id=1 的数据

BEGIN 
select * from testdemo where id =1 for update

然后在另一个session 中

update testdemo set c1 = '1' where id = 2 成功 
update testdemo set c1 = '1' where id = 1 等待

id=1等待验证了两个事务不能锁同一个索引

然后rollback结束当前事务,接着

BEGIN 
update testdemo set c1 = '1' where id = 1

注意,这里使用update时后面没有加for update
然后在另外一个 session 中

update testdemo set c1 = '1' where id = 1 等待

我们发现即使没有加for update,一样锁住了

结论: insert ,delete , update在事务中都会自动默认加上排它锁(写锁)。

继续,先放一下当前表中的数据内容
在这里插入图片描述

BEGIN 
update testdemo set c1 = '1' where c1 = '1' 
在另外一个 session 中 
update testdemo set c1 = '2' where c1 = '2' 等待

按道理我在操作从=1时只锁住了c1=1的哪一行,为什么c1=2的这一行也被锁住了呢,因为上面创建表时c1并没有加索引

结论: 行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。

最后小结

注意 : 行锁释放锁时用rollback或commit,表锁使用 UNLOCK TABLES 或者 begin 来解锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值