一文搞懂MySQL中的 ‘锁‘

表级锁 行级锁

从 锁的粒度 来分, 分为 表级锁 和 行级锁

  • 表级锁: 一般是存储引擎不支持行锁时才使用

  • 行级锁: 当SQL语句对记录进行读写操作时, 可以选择对记录加行锁

    • 正经记录锁: 最常用的行级锁, 仅仅把一条记录锁上
    • gap锁: 会锁住 该记录与上一记录的间隙
    • next-key锁: 会锁住 该记录 和 该记录与上一记录的间隙
      • 加S型next-key锁: select * from table where id>1 and id<=6 lock in share mode;
      • 加X型next-key锁: select * from table where id>1 and id<=6 lock for update;
    • 插入意向锁: 表明有事务想在某个间隙插入新记录, 但现在处于等待状态

共享锁 独占锁 意向锁

从 锁的模式 来分, 分为 共享锁, 独占锁, 意向锁

  • 共享锁 (Share): 简称S锁, 行级或表级, 允许所有事务读取该记录, 但不允许修改
    • 哪些语句会自动加S锁: 无
    • 怎么手动加S锁:
      • 对读取的记录行加S锁: select … lock in share mode;
      • 对整张表加S锁: lock tables t read;
  • 独占锁 (Exclusive): 简称X锁, 行级或表级, 只允许本事务读写该记录
    • 哪些语句会自动加X锁: update, delete, insert
    • 怎么手动加X锁:
      • 对读取的记录行加X锁: select … for update;
      • 对整张表加X锁: lock tables t write;
  • 共享意向锁: 简称IS锁, 是表级锁, 仅用来判断表中是否有记录上了S锁
  • 独占意向锁: 简称IX锁, 是表级锁, 仅用来判断表中是否有记录上了X锁
  • 自增锁: 用于给auto_increment字段递增赋值, 只作用于单个插入语句, 插入完成后立刻释放

注: 普通的select语句不加任何锁, 根据 隔离级别的不同, 会读取记录的最新版本 或 MVCC版本链记录

悲观锁 乐观锁

从 锁的风格 来看, 分为 悲观锁 和 乐观锁

  • 悲观锁: 每次获取数据的时候,都默认别人会修改这个数据,所以都会上锁,这样就会阻止其他人访问该数据,直到事务结束才释放锁
# 原生SQL
begin;
select stock from tb_sku where id=1 for update;
update tb_sku set stock=2 where id=1;
commit;

# ORM
sku = SKU.objects.select_for_update().get(id=1)
sku.stock=2
sku.save()
  • 乐观锁: 每次获取数据的时候,都默认别人不会修改这个数据,所以不会加锁,只有在更新的时候会判断在此期间这个数据是否被更改
# 原生SQL
select stock from tb_sku where id=1;  # 假设这里查到库存为7
# 判断下单数量 是否大于 库存
update tb_sku set stock=2 where id=1 and stock=7;

# ORM
SKU.objects.filter(id=1, stock=7).update(stock=2)

你可能感兴趣的:(MySQL,mysql)