0、 查看方式
-
innodb锁:
select * from information_schema.innodb_trx\G -
innodb引擎状态查锁:
set global innodb_status_output_locks=1;
show engine innodb status\G -
行锁:
select * from performance_schema.data_locks\G -
行锁等待:
select * from performance_schema.data_lock_waits\G -
mdl锁:
select * from performance_schema.metadata_locks\G -
锁等待:
select * from sys.schema_table_lock_waits;
show processlist;
show engine innodb status\G
sys var:innodb_status_output&innodb_status_output_locks
sys.innodb_lock_waits
sys.schema_table_lock_waits
pfs.data_locks
pfs.data_lock_waits
pfs.metadata_locks
1、 共享锁
-
加锁:
select ... [for share]|[lock in share mode] -
查看:
select * from information_schema.innodb_trx\G
2、 排他锁
select .. for update
3、 意向锁
加在锁上面。IS 意向共享锁, IX意向排他锁。
意向锁是加载在数据表B+树根节点,也就是说对整个表加意向锁。
意向锁的作用:避免在执行DML时,对表执行DDL操作,导致数据不一致
4、行锁案列
- 排他锁与任何锁冲突
- 排他锁不影响一致性读
- 无索引的列,锁全表
- 有索引的列,空记录共享 gap lock
- 意向插入锁被gap lock阻塞
- 有索引,相同条件互斥
- 注意每个列锁的位置
- 范围扫描,加 lock_ordinary
5、InnoDB锁实现
5.1 InnoDB行锁实现机制
基于索引实现
逐行检查,逐行加锁
没有索引的列上需要加锁时,会先对所有记录加锁,再根据实际情况决定是否释放锁
辅助索引上加锁时,同时要回溯到主键索引上再加一次锁
5.2 InnoDB行锁之共享锁
共享锁,不允许其它事务修改被锁定的行,只能读
select .. from... for [share]|[lock in share mode]
自动提交模式下的普通select是一致性非锁定读,不加锁
5.3 InnoDB行锁之排它锁
对一行记录进行DML时,需至少加上排它锁
锁范围视情况而定,可能是record lock、next-key lock,或者可能只有gap lock
执行DML,或 select ... for update
5.4 InnoDB行锁之意向锁
IS(intention shared),事务T想要获得表中某几行的共享锁
IX(intention exclusive),事务T想要获得表中某几行的排它锁
意向锁是加载在数据表B+树结构的根节点,也就是对整个表加意向锁
意向锁的作用:避免在执行DML时,对表执行DDL操作,导致数据不一致。
5.5 lock_ordinary
著名的next-key lock,锁住记录本身,及其GAP
在RR级别下,利用next-key lock 来避免产生幻读
当innodb_locks_unsafe_for_binlog=1时,会降级为lock_rec_not_gap,相当于降级到RC
8.0之后废弃了innodb_locks_unsafe_for_binlog参数。
5.6 lock_rec_not_gap
仅记录锁,仅锁住记录本身,不锁其前面的GAP
RC下的行锁大多数都是这个锁类型
RR下的主键、唯五索引等值条件下加锁通常也是这个锁类型
RR下非唯一索引加锁时(lock_ordinary),也会同时回溯到主键上加lock_rec_not_gap锁。当唯一性约束检测时,即使在RC下,总是要先加lock_s | lock_ordinary锁。
5.7 lock_gap
避免发生幻读。
间隙锁,只锁住索引记录之间、或第一条索引记录(infimum)之前、又或最后一条索引记录(supremum)之后的范围,并不锁住记录本身
5.8 lock_insert_intention
插入意向锁,是一种特殊的gap lock,当插入索引记录的时候用来判断是否有其他事务的范围冲突,如果有就需要等待。
同一个gap中,只要不是同一个位置就可以有多个插入意向锁并存
例如[5]~[10]区间中,同时插入[6]、[8]就不会相互冲突阻塞,而同时插入两个[9]就会引发冲突阻塞等待
但是lock_insert_intention 和 lock_gap并不兼容。
网友评论