Mysql锁理论

1.使用MYISAM引擎存储(只能加表锁)

  • 给表加读锁 lock table table_name read;
  • 给表加写锁 lock table table_name write;
    建表语句:
    在这里插入图片描述

下面进行读写锁的特性测试:
1.首先是读锁:
在这里插入图片描述
在对一个数据库中的表加了读锁时,自身还可以读取该表的记录。但是不能读取其它表的记录。

在这里插入图片描述
自己不能更新表中的记录。

那么在另一个新开的会话当中的情况呢?
在这里插入图片描述
可以读取任意表的信息,更新操作将会被阻塞。

2.再是写锁
在这里插入图片描述
在自身的会话中,写锁可以读,写,不能查看其它的表。

在这里插入图片描述
在新开的会话中,不能读,写。

结论:在MYISAM引擎体系下,读锁会限制自己更新,查看其它会话的。并且新开的会话的更新操作会被阻塞,可以读取记录。加写锁是,自身的更新和查询都没问题,新开的会话更新和读取都会阻塞。

2.在INNODB引擎体系下的锁(重点)

INNODB是支持行锁(锁住一条记录),也支持表锁的,下面进行详细的讲解。
实验用到的表结构:
在这里插入图片描述
id字段作为主键,category_id和views字段作为联合索引。

1.INNDOB的行锁
INNDOB引擎体系下,当我们使用set autocommit=false; 或者start transaction;开启事务时,update,insert,和delete操作会自动为我们操作的那一行数据加上共享锁(写阻塞,读共享)。注意,行锁只会在我们操作索引字段的时候生效。具体的原因我稍后解释。

在这里插入图片描述
会话一开启事务,并且where条件处根据索引字段查找,改变title记录为2,按照加共享锁的思想,这一行已经不能再被更新,除非我们提交事务。下面验证:

在这里插入图片描述
会话二同样开启事务,并尝试更新会话一已经上锁的一行记录,可以看到,此时阻塞时间太行,已经更新失败。但是我们查看该行行记录是没有问题的。并且也不会阻塞我们更新其它的行记录。

上面提到,为什么需要用索引来检索我们需要更新的行呢?其实了解索引工作原理的朋友应该都明白,如果我们没有为一个字段建立索引,那么where查找时,就会在原生的表中直接一一匹配,而Mysql是采取 "宁可错杀,不可放过"的思想,把我们检索过的行记录都一一上锁,这个时候,我们的行锁就相当于变成了表锁。一个字段上建立了索引并且生效时,我们只需要去索引表中快速查找指定记录,不会扫描整表。

2.间隙锁
何谓间隙锁?简而言之,当我们使用范围条件检索数据而不是等值条件,并且请求共享锁或者排它锁,对于在检索范围内但是实际上并不存在的数据记录,INNODB引擎体系下也会加锁。
做一个案例充分感受以下:
在这里插入图片描述
可以看到表中并不存在id为2的记录,这是我为了测试特意剔除的数据。尝试在另一个会话中插入id为2的数据:
在这里插入图片描述
由于阻塞时间过长导致更新失败。这就是间隙锁,注意要防范这种锁的产生。

3.手动加上共享锁和排它锁
上述的锁都是被动产生的,处于事务中时,Mysql的INNODB引擎会自动为更新操作加上共享锁。但是如果我们想自己加呢?
看接下来的演示。
在这里插入图片描述
select * from table_name where id=? for update表示为该行记录上排它锁。
在这里插入图片描述
可以看到在另一个会话当中更新上锁记录失败。注意,这种情况下不要求检索的字段是添加了索引索引的字段。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值