June's Studio.

MySQL-锁总结

字数统计: 527阅读时长: 2 min
2021/08/08

种类

行锁 & 表锁

明确主键,执行行锁,否则表锁

  • 无锁:主键id不存在
1
select * from t where id = -1 for update;
  • 行锁 : 明确主键
1
2
select * from t where id = 1 for update;
select * from t where id = 1 and name like 'kkk%' for update;
  • 表锁
1
2
3
#主键不明确
select * from t where name like 'kkk%' for update;
select * from t where id <> 111 for update;

机制

行锁机制

record Lock (普通行锁)

  • 键值在条件范围内,且记录存在

gap lock(间隙锁)

  • 对于键值不存在条件范围内, 引擎会对这个间隙加锁

next-key lock (行 +间隙)

  • 在键值范围条件内,同时键值又不存在条件范围内
1
2
# 这张表id 1-50 
select * from t where id > 49 for update ;

表锁机制

意向锁

  • 当一个事务带着表锁去访问一个带着行锁的资源,行锁被升级为意向锁,将表锁住
1
2
3
4
# 事务A - 升级为意向锁
select * from t where id = 50 for update ;
# 事务B - 表锁
select * from t where name = 'kkk' for update;

自增锁

  • 事务插入自增类型的列,获取自增锁

    如果一个事务正在表中插入自增记录,其他事务必须等待

实现

共享锁 & 排他锁

行锁和表锁 是粒度的概念 ,排他锁是具体的实现

共享锁 (S)

  • 允许一个事务去读一行数据,阻止其他事务获得该行的排它锁

排它锁(X)

  • 允许持有排他锁的事务读写数据,组织其他事务获得排它锁和共享锁

注意点

某个事务获取事务的排它锁,其他事务不能获取改事务的任何锁,并不代表其他事务不能无锁读取该数据

  • 无锁
1
select ... from ...
  • 共享锁
1
select ... lock in share mode;  

8.0以上 for share 代替了 lock in share mode,但仍然支持lock in share mode。但是 nowait, skip locked ,配合自旋锁,可以高效实现一个等待队列

  • 排它锁
1
2
3
4
update 
delete
insert
select ... for update

乐观锁 & 悲观锁

  • 乐观锁

通过版本号实现

  • 悲观锁
CATALOG
  1. 1. 种类
    1. 1.1. 行锁 & 表锁
    2. 1.2. 机制
      1. 1.2.1. 行锁机制
      2. 1.2.2. 表锁机制
    3. 1.3. 实现
      1. 1.3.1. 共享锁 & 排他锁
        1. 1.3.1.1. 共享锁 (S)
        2. 1.3.1.2. 排它锁(X)
        3. 1.3.1.3. 注意点
        4. 1.3.1.4. 乐观锁 & 悲观锁