加什么锁

参考资料:

不同事务隔离级别下


聚簇/非聚簇索引上都有可能加锁

  • 原则
    1. 加锁的基本单位是 Next-Key Locks, 是一个前开后闭区间。
    2. 查找过程中访问到的对象才会加锁。
  • 优化
    1. 索引上的等值查询,给唯一索引加锁的时候,Next-Key Locks 退化为Record Locks 记录锁。
    2. 索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,Next-Key Locks 退化为Gap Locks 间隙锁。
  • 一个 bug: 唯一索引上的范围查询会访问到不满足条件的第一个值为止。

Example

比如一个表 id 为主键, 有如下数据

0 5 10 15 20 25

执行 select * from t where id>10 and id<=15 for update

根据原则 1,加锁单位是 next-key lock,会给 (10,15]加上 next-key lock,并且因为 id 是唯一键,所以循环判断到 id=15 这一行就应该停止了。

但是,InnoDB 会往前扫描到第一个不满足条件的行为止,也就是 id=20。而且由于这是个范围扫描,因此索引 id 上的 (15,20]这个 next-key lock 也会被锁上。

update 没加索引会走全表?

在 update 语句的 where 条件没有使用索引,就会全表扫描,于是就会对所有记录加上 next-key 锁(记录锁 + 间隙锁),相当于把整个表锁住了

锁分类

全局锁

FLUSH TABLES WITH READ LOCK

表级锁

行锁

其他

See also