【mysql】- 锁篇(下)
InnoDB存储引擎中的锁
- 表级锁
- 表级别的
S锁
、X锁
- 在对某个表执行
SELECT
、INSERT
、DELETE
、UPDATE
语句时,InnoDB
存储引擎是不会为这个表添加表级别的S锁
或者X锁
的
- 在对某个表执行
- 表级别的
IS锁
、IX锁
- 当我们在对使用
InnoDB
存储引擎的表的某些记录加S锁
之前,那就需要先在表级别加一个IS锁
,当我们在对使用InnoDB
存储引擎的表的某些记录加X锁
之前,那就需要先在表级别加一个IX锁
。IS锁
和IX锁
的使命只是为了后续在加表级别的S锁
和X锁
时判断表中是否有已经被加锁的记录,以避免用遍历的方式来查看表中有没有上锁的记录
- 当我们在对使用
- 表级别的
AUTO-INC锁
- 在使用
MySQL
过程中,我们可以为表的某个列添加AUTO_INCREMENT
属性,之后在插入记录时,可以不指定该列的值,系统会自动为它赋上递增的值
- 在使用
- 表级别的
- 行级锁:
行锁
,也称为记录锁
,顾名思义就是在记录上加的锁行锁
类型Record Locks
:有S锁
和X锁
之分,当一个事务获取了一条记录的S型记录锁
后,其他事务也可以继续获取该记录的S型记录锁
,但不可以继续获取X型记录锁
;当一个事务获取了一条记录的X型记录锁
后,其他事务既不可以继续获取该记录的S型记录锁
,也不可以继续获取X型记录锁
Gap Locks
:可以用于解决可重复读级别下的幻读问题,防止插入幻影记录Next-Key Locks
: 锁住某条记录同时又可以阻止其他事务在该条记录前边的间隙
插入新纪录,其是Record Locks
和gap Locks
的合体它既能保护该条记录,又能阻止别的事务将新记录插入被保护记录前边的间隙
Insert Intention Locks
:一个事务在插入一条记录时需要判断一下插入位置是不是被别的事务加了所谓的gap锁
,若存在,插入操作需要等待,直到拥有的gap锁
对应的事务提交,事务在等待的时候也需要在内存中生成一个锁结构
,表明有事务想在某个间隙
中插入新纪录,但是现在在等待。这种类型的锁命名为Insert Intention Locks
,也成为插入意向锁
隐式锁
:一个事务在执行INSERT
操作时,如果即将插入的间隙已经被其他事务加了gap
锁,那么本次INSERT
操作会阻塞,并且当前事务会在该间隙上加一个插入意向锁
,否则一般情况下INSERT
操作是不加锁的
内存结构
- 加锁的本质就是在内存中创建一个
锁结构
与之关联- 对于需要放在同一个
锁结构
中的情况- 在同一个事务中进行加锁操作
- 被加锁的记录在同一个页面中
- 加锁的类型是一样的
- 等待状态是一样的
- 对于需要放在同一个
- 锁结构
锁所在的事务信息
: 不论是表锁
还是行锁
,都是在事务执行过程中生成的,哪个事务生成了这个锁结构
,这里就记载着这个事务的信息。其本质是一个指针,通过该指针可以找到内存中关于该事务的更多信息索引信息
:对于行锁
来说,需要记录一下加锁的记录是属于哪个索引的表锁/行级信息
:表锁
:记载着这是对哪个表加的锁,还有其他的一些信息行锁
:记载了三个重要的信息- Space ID :记录所在表空间。
- Page Number :记录所在页号。
- n_bits :对于行锁来说,一条记录就对应着一个比特位,一个页面中包含很多记录,用不同的比特位来区分到底是哪一条记录加了锁。为此在行锁结构的末尾放置了一堆比特位,这个
n_bits
属性代表使用了多少比特位
type_mode
:这是一个32位的数,被分成了lock_mode
、lock_type
和rec_lock_type
三个部分- 锁的模式( lock_mode ),占用低4位
LOCK_IS
(十进制的0
):表示共享意向锁,也就是IS锁
。LOCK_IX
(十进制的1
):表示独占意向锁,也就是IX锁
。LOCK_S
(十进制的2
):表示共享锁,也就是S锁
。LOCK_X
(十进制的3
):表示独占锁,也就是X锁
。LOCK_AUTO_INC
(十进制的4
):表示AUTO-INC锁
。
- 锁的类型( lock_type ),占用第5〜8位,不过现阶段只有第5位和第6位被使用:
LOCK_TABLE
(十进制的16
),也就是当第5个比特位置为1时,表示表级锁。LOCK_REC
(十进制的32
),也就是当第6个比特位置为1时,表示行级锁
- 行锁的具体类型(
rec_lock_type
),使用其余的位来表示。只有在lock_type
的值为LOCK_REC
时,也就是只有在该锁为行级锁时,才会被细分为更多的类型:LOCK_ORDINARY
(十进制的0
):表示next-key
锁 。LOCK_GAP
(十进制的512
):也就是当第10个比特位置为1时,表示gap锁
。LOCK_REC_NOT_GAP
(十进制的1024
):也就是当第11个比特位置为1时,表示记录锁
。LOCK_INSERT_INTENTION
(十进制的2048
):也就是当第12个比特位置为1时,表示插入意向锁
- 锁的模式( lock_mode ),占用低4位
明明可以靠才华吃饭,非要靠脸~