【锁专题】锁常见问题
本问题对应的项目链接:高频题回答模版训练
这块一般不难,可能会结合性能优化来问
1、mysql 有哪些锁,介绍一下?
2、mysql是怎么实现乐观锁和悲观锁的?
3、哪些情况下会使用乐观锁,哪些情况使用悲观锁,可以举一些 sql 例子吗?
4、间隙锁的原理?什么时候会加间隙锁?
本问题对应的项目链接:高频题回答模版训练
这块一般不难,可能会结合性能优化来问
1、mysql 有哪些锁,介绍一下?
2、mysql是怎么实现乐观锁和悲观锁的?
3、哪些情况下会使用乐观锁,哪些情况使用悲观锁,可以举一些 sql 例子吗?
4、间隙锁的原理?什么时候会加间隙锁?
共以下 3 个回答
1、mysql 有哪些锁,介绍一下?
mysql中有全局锁、表锁、行锁、间隙锁等。
2、mysql是怎么实现乐观锁和悲观锁的?
3、哪些情况下会使用乐观锁,哪些情况使用悲观锁,可以举一些 sql 例子吗?
当对数据进行数据读多写少的时候一般用乐观锁,如果是对数据进行改多读少则使用悲观锁。
4、间隙锁的原理?什么时候会加间隙锁?
间隙锁是指在两个数据索引的间隙加上锁,使得其他线程对该间隙的增删改操作都被阻塞。当我们对一组数据上锁的时候,并且隔离级别为可重复读的时候,便会自动加上间隙锁。
1、mysql 有哪些锁,介绍一下?
按照锁的粒度,可以分为全局锁,表级锁和行锁。
全局锁会使整个数据库处于只读状态,在做全库逻辑备份时经常用到;表级锁在操作数据时会锁定整张表或表结构,具体可以分为表锁,MDL 锁和意向锁;行锁可以做到只锁定需要操作的记录行或间隙,具体可以分为记录锁,间隙锁和 临键锁,也就是记录锁加间隙锁的组合,它锁的是一个范围。
2、mysql是怎么实现乐观锁和悲观锁的?
(看情况简单说一下乐观锁是…多线程基础那有嘞)
MySQL 中通常使用版本号或者时间戳来实现乐观锁。以版本号为例,可以在数据表中添加一个版本号字段,然后当某个事务中需要更新一条记录时,直接用 where 语句对版本号进行等值判断,如果与给定的版本号相同则更新,不相同则整个事务回滚或重试。用时间戳实现也是类似的方式。整个过程不需要锁整个表,只需简单判断版本号即可。
(悲观锁是…)
MySQL 中通常使用
for update或lock in share mode语句来实现悲观锁。具体的,在事务开启时先执行select ... for update给所有记录加上 临键锁,防止其他事务干扰,然后执行更新操作,在事务结束时释放锁,后续事务才能获得锁而继续进行。整个过程就是悲观锁的思想:先悲观的整体加锁,等所有更新操作完成再释放。3、哪些情况下会使用乐观锁,哪些情况使用悲观锁,可以举一些 sql 例子吗?
乐观锁适用于读多写少,也就是并发冲突很少的场景,这样可以省去锁的开销,提高系统的吞吐量。悲观锁适用于读少写多的场景,这样可以避免在并发冲突多的情况下,使用乐观锁带来的不断重试问题。这时用悲观锁为每个事务上锁就比较合适。
举例的话,可以考虑这样的场景:有用户 A 和用户 B,同时去买同一件商品,但商品的数量只有一个。
乐观锁的实现是在商品表中添加一个 version 字段,然后直接指定版本号更新。假设 MySQL 为 RR 隔离级别,都要买 id = 1 的商品,version 初始为 0,用户 A 对应 SQL 为
用户 B 对应的 SQL 为
虽然用户 A 和 用户 B 在 T1,T2 时刻都看到还有一件商品,但最终只有用户 A 在 T3 时刻能够获得最后一件商品,此时 version 自增为 1,那么用户 B 在 T4 时刻将无法找到这条记录,也就无法购买成功。
悲观锁的实现直接在事务开始时给所有记录上锁,直到事务结束再释放锁。用户 A 和 B 对应的 SQL 一样,都是
由于用户 A 在事务开始时就对数据加了 临键锁,用户 B 只能等到用户 A 在事务结束释放锁时再执行,最终还是只有用户 A 能购买。
4、间隙锁的原理?什么时候会加间隙锁?
对于行锁来说,数据行是可以加上锁的实体,但其实数据行之间的间隙也是可以加上锁的实体,对应的锁就是间隙锁。间隙锁锁的是数据库中两个值的间隙,目的是防止往这个间隙中插入一条新记录,以此来防止幻读。
间隙锁通常出现在 InnoDB 引擎的可重复读隔离级别下,并且行锁加间隙锁,也就是临键锁是加锁的基本单位。但在某些情况下,临键锁也会退化成行锁或者间隙锁。
mysql有全局锁,在全库备份时使用。表级别的读锁、写锁实现读写互斥,Innodb存储引擎还有更细粒度的行锁实现读写互斥。表级别的元数据锁用来保证表结构的一致性。行级别的间隙锁解决幻读导致的数据不一致问题。
mysql通过CAS操作来比较版本号或者时间戳判断原来数据是否被其它线程修改实现乐观锁,update和delete语句存储引擎层会自动加上悲观锁,select语句可以加上for update加上悲观锁。
在锁冲突频率小、响应速度要求高、重试代价不大的场景下,就可以使用乐观锁。
比如每日优惠劵的抢购。
在锁冲突比较严重、响应速度要求不高或者重试代价很大的场景下,就采用悲观锁。
比如秒杀场景。1000万用户在10分钟内抢购商品,一分钟就有100万次请求,一秒16万次请求。