MySQL 锁类别
全局锁
flush tables with read lock;
unlock tables; // 解锁
这样表就处于只读状态了,全库逻辑备份就需要用这个。
表级锁
表锁
lock tables `table_name1` read, `table_name2` read; # 读锁
lock tables `table_name` write, `table_name2` write; # 写锁
unlock tables; # 解锁或者退出会话自动解锁
- 读锁:只能对当前表进行读,不能对当前表进行写,也不能访问其他表。其他会话只能读这张表,不能写这张表。
元数据锁
元数据锁(MDL)
对一张表进行
crud
,加上MDL
读锁。对一张表结构进行改变,会加上
MDL
写锁。
MDL是自动上锁自动解锁的,整个事务期间都会有
意向锁
当加行级锁(如增,删,改时)会先加上表级别的意向锁,这样如果需要加表锁的话,可以通过检查意向锁而不需要逐行检查表锁,加快速度。
- 意向共享锁:对行级别加共享锁之前,需要对表级别加意向共享锁。
- 意向独占锁:对行级别加独占锁之前,需要对表级别加意向独占锁。
AUTO-INC锁
主键自增时也会发生重读,auto-inc
锁就是为了主键自增设计的锁,可以更改环境变量innodb_autoinc_lock_mode
来改变锁的行为
innodb_autoinc_lock_mode=0
,语句执行结束后才释放innodb_autoinc_lock_mode=2
,轻量级锁,主键增加后就释放innodb_autoinc_lock_mode=1
:- 普通
select
锁,申请后马上释放 insert ... select
批量插入语句,等语句结束才释放
- 普通
行级锁
InnoDB
支持行级锁,MyISAM
不支持。
普通select
不会加锁,因为属于快照读,只需要MVCC
即可。在事务中,才会进行锁定读,可以使用如下命令:
select ... lock in share mode; -- 共享锁
select ... for update; -- 独占锁
事务提交了,锁就会释放了。
- Record lock:记录锁,锁住某一条记录。分为共享锁(
S
)和独占锁(X
)之分。 - Gap lock:间隙锁,锁定某个范围(开区间,不会锁定记录本身),只有共享锁,但是会阻塞
insert
语句 - Next-Key Lock:记录锁+间隙锁,锁定一个返回(可以为前开后闭区间,也会锁定记录本身),有共享锁(
S
)和独占锁(X
)之分,并且对范围内的记录都是有独占锁和共享锁之分的。 - 插入意向锁:在插入数据时,如果被其他事务的锁阻塞了,那么就会设置一个插入意向锁,它是一个特别的间隙锁,与间隙锁是互斥的。
加锁规则
行级锁是以next-key lock
作为基本单位的,next-key lock
是前开后闭区间,间隙锁是开区间
- 唯一索引等值查询
- 记录存在,那么就是对该条记录加锁,退化成记录锁
- 记录不存在,那么找到第一个大于该记录并加锁,退化成间隙锁
- 唯一索引范围查询
- 针对
>=
查询时:由于等值存在,所以会退化成记录锁 - 针对
</<=
查询时:
- 针对
- 非唯一索引等值查询
- 非唯一索引范围查询