前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >工作面试老大难-锁(下)

工作面试老大难-锁(下)

作者头像
热心的大肚皮
发布2023-02-28 14:03:22
2430
发布2023-02-28 14:03:22
举报
文章被收录于专栏:程序猿日常笔记

大家好,我是热心的大肚皮,皮哥。

InnoDB锁的内存结构

直接上图,我们看看InnoDB中锁的结构。

  • 锁所在的事务信息:任何锁都属于一个事务,这里记载对应的事务信息。
  • 索引信息:对于行级锁来说,需要记录加锁的记录属于哪个索引。
  • 表/行锁信息:记录的对应的信息。
  • type_mode:32比特的数,包含lock_mode、lock_type、rec_lock_type这三部分。
    • lock_mode(锁模式)占用低4比特。
      • LOCK_IS(十进制的0):共享意向锁。
      • LOCK_IX(十进制的1):独占意向锁。
      • LOCK_S(十进制的2):共享锁。
      • LOCK_X(十进制的3):独占锁。
      • LOCK_AUTO_INC(十进制的4):AUTO_INC锁,轻量级锁。
    • lock_type(锁类型)占用第5-8位。
      • LOCK_TABLE(十进制的16):也就是当第五比特设置为1时,表示表级锁。
      • LOCK_REC(十进制的32):也就是当第六比特设置为1时,表示行级锁。
    • rec_lock_type代表行锁的具体类型,不过多讲述了。不过这里面有个关键的属性。
      • LOCK_WAIT(10进制的256):也就是第九比特设置为1时,表示is_waiting为true,即当前事务尚未获取到锁,等待中,反之is_waiting为false,即事务获取锁成功。
  • 其他信息:不用关注。
  • 比特位:映射到页中的记录。

InnoDB行锁的分类

  • Record Lock:记录锁。只对记录本身加锁。
  • Gap Lock:锁住记录前的间隙,防止别的事物向该间隙插入新纪录。在repeatable read隔离级别下可以很大程度解决幻读,解决方案有两种:一种是MVCC,另一种就是使用这种锁。
  • Next-Key Lock:Record Lock与Gap Lock的结合体,既保护记录本身,也防止别的事务插入记录。
  • Insert Intention Lock:某个事务获取这种锁后,不会阻止别的事务继续获取这个记录上任何类型的锁,这个可以忽略。
  • 隐式锁:依靠记录的trx_id属性来保护不被别的事务改动记录。

在InnoDB存储引擎中,锁都对应一个结构,为了节约内存,会把符合要求的锁放到同一个锁结构中:

  • 在同一个事物中进行加锁操作;
  • 被加锁的记录在同一个页面中;
  • 加锁的类型都是一样的;
  • 等待状态是一样的。

死锁

假设我们开启了两个事务T1和T2,如下。

执行顺序

T1

T2

1

begin;

2

begin;

3

select * from hero where id=1 for update;

4

select * from hero where id=3 for update;

5

select * from hero where id=3 for update;

6

select * from hero where id=1 for update;

通过上面的执行顺序可以发现,事务T1第5步执行时,在等待事务T2中的第4步,而事务T2中第6步在等待事务T1中的第3步,它们在互相等待,造成死锁,InnoDB中有个死锁检测机制,当检测到死锁时,会选择一个较小的事务进行回滚(指事务执行过程中增删改操作记录少的事务),而且会给客户端发送Deadlock found when trying to get lock。发生了死锁,我们一般会采用SHOW ENGINE INNODB STATUS命令来查看最近一次的死锁信息。

具体应用场景

读操作

  • 这种普通的读操作在READ COMMITTED 和 REPEATABLE READ(默认的)级别下,都是利用MVCC来控制,只是拍快照的时机不一样。
代码语言:javascript
复制
SELECT ....FROM .. 
  • 特殊的select会加锁
代码语言:javascript
复制
SELECT ... LOCK IN SHARE MODE;  -- 加读锁
SELECT ... FOR UPDATE;  --加写锁

写操作

  • 只有INSERT特殊,一般不加锁(但是别的事务有干扰的情况下,别的事务会来帮执行INSERT的这个事务的行记录加锁)
  • 其他普遍都得加锁,比如UPDATE(一般是先删除后插入),DELETE
    • 有索引:
      • 在READ COMMITTED :普通的写锁
      • 在REPEATABLE READ
        • 除非是唯一索引且等值的条件:加普通的写锁
        • 其他普遍情况加的都是next-key锁(普通写锁+间隙锁)
    • 无索引:全表都加锁
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序猿日常笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档