MySQL锁 读锁和写锁,行级锁和表级锁

读锁:也叫共享锁,Share Lock,S锁,当一个事务添加读锁后,其他事务也可以获取这个共享锁来读取数据,但是不能进行写数据(获取读锁的事务只能读,不能写),只有等到所有的读锁都释放了,才能写数据

上读锁,而且是行级读锁

select * from  student where name=‘小明’ lock in share mode;

写锁:也叫排他锁,Exclusive Lock,X锁,当一个事务添加了写锁之后,其他事务无法获取这个锁,无法读也无法写,只能等待当前事务释放写锁

上写锁,而且是行级写锁

select  *  from student  where student_id=1  for  update

行级锁和表级锁:MyIsam引擎只支持表级锁,InnoDB引擎既支持表级锁,也支持行级锁

表级锁:mysql中粒度最大的锁,对整张表加锁,实现起来简单,资源消耗也比较少,不会出现死锁,但是由于其粒度太大,触发锁冲突的概率也是最大的,并发写的情况下性能非常差

表级锁针对非索引字段加锁

行级锁:mysql中粒度最小的锁,只对当前操作的行记录(一行或者多行)进行加锁,大大减少了锁冲突的情况,但是加锁的开销也是最大的。而且会出现死锁

行级锁针对索引字段加锁

行锁可以进一步进行分类:记录锁,间隙锁,临键锁,这三个锁都是写锁

(1)记录锁  record locks

仅仅锁住一行

这个就是记录锁

SELECT * FROM `test` WHERE `id`=1 FOR UPDATE;

(2)间隙锁  gap lock

左开右开区间,也就是不包括双端端点

创建一张表,表里面只有两个字段id 和name

CREATE TABLE `test` (
  `id` int(1) NOT NULL AUTO_INCREMENT,
  `name` varchar(8) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `test` VALUES ('1', '小罗');
INSERT INTO `test` VALUES ('5', '小黄');
INSERT INTO `test` VALUES ('7', '小明');
INSERT INTO `test` VALUES ('11', '小红');

执行下面的sql语句,发现

BEGIN;

SELECT * FROM `test` WHERE `id` BETWEEN 5 AND 7 FOR UPDATE;

INSERT INTO `test` (`id`, `name`) VALUES (3, '小张1'); # 正常执行

INSERT INTO `test` (`id`, `name`) VALUES (4, '小白'); # 正常执行

INSERT INTO `test` (`id`, `name`) VALUES (6, '小东'); # 阻塞

INSERT INTO `test` (`id`, `name`) VALUES (8, '大罗'); # 阻塞

INSERT INTO `test` (`id`, `name`) VALUES (9, '大东'); # 阻塞

INSERT INTO `test` (`id`, `name`) VALUES (11, '李西'); # 阻塞

INSERT INTO `test` (`id`, `name`) VALUES (12, '张三'); # 正常执行

COMMIT;

可以看到,(5, 7]、(7, 11] 这两个区间,都不可插入数据,其它区间,都可以正常插入数据。所以所以锁住的是[5,11]

(3)临键锁  next key lock  可以理解为一种特殊的间隙锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据(临键锁只与非唯一索引有关,唯一索引不存在临键锁)

什么时候会加上临键锁:select * from  table  for  update;

或者update  XX的时候就会获取到该行记录的临键锁

 现在在事务A中执行以下命令:(只开启事务,不提交事务)

start  transaction;

update  student  set email='zm@alibaba-inc.com' where age=26;

更改赵敏的email邮箱  ,此时会锁住的是(26,77]   

现在事务B执行下面的命令:

start  transaction;

insert into student values("s010","牛牛",28,’女‘,“13344453233”,“2658948489@qq.com”,“1988-02-11“,0);

commit;

 发现没有插入成功,因为你插入的age=28,除在被锁住的age=(26,77] 区间内,没有拿到这把临键锁的事务B无法插入成功

只有事务A提交了,才会不锁住这个区间,事务B才能插入成功

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值