MySQL全表锁不是表级锁

2023年 10月 17日 16.5k 0

场景

在MySQL-innodb引擎的RR(REPEATABLE-READ)隔离级别下。

当update t set a_column=99 where name=‘张三’;

如果name字段上没有索引,那么行锁将上升为表锁。

重点来了

这句话中,行锁将上升为表锁

  • 正确理解:单行锁将上升为全部行锁(即全表锁)。
  • 错误理解:行级锁将上升为表级锁。

你品,你细细品

MySQL-innodb引擎加锁原理

这里就不赘述什么共享锁、排查锁、记录锁、间隙锁等等了。主要是说明两点
1、innodb引擎加行锁都是加在索引上的。也很好理解,因为查询也是通过索引,或索引回表来的,行锁当然也是加在索引上的。
2、为什么where的字段没有索引就会从行锁上升为“表锁”,因为没有索引的时候会进行全表扫描,然后把每一个聚簇索引(或隐藏的聚集索引)都锁住。

实验

CREATE TABLE t (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
age int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

数据:
1 张三 11
2 李四 12
3 王五 13

隔离级别RR

实验一:
  • name字段没有索引
  • 会话1:update t set age=111 where name=‘张三’;
  • 会话2:update t set age=112 where name=‘李四’;
  • 会话3:lock tables t write或lock tables t read;

结论:

  • 由于name字段没有索引,行锁上升为表锁,所以会话2无法提交,会话3也无法提交。

  • 查看是否有表锁:无表锁

实验二
  • name字段有索引
  • 会话1:update t set age=111 where name=‘张三’;
  • 会话2:update t set age=112 where name=‘李四’;
  • 会话3:lock tables t write或lock tables t read;

结论:

  • name字段有索引,所以会话2正常提交,会话3依旧无法提交

  • 查看是否有表锁:无表锁

实验三
  • name字段有索引
  • 会话1:lock tables t write或lock tables t read;
  • 会话2:update t set age=111 where name=‘张三’;

结论:

  • t表被锁表,所以会话2无法提交

  • 查看是否有表锁:有表锁

实验四
  • name字段有索引
  • 会话1:lock tables t write或lock tables t read;
  • 会话2:select * from t;

结论:

  • t表被锁定读时,会话2可以查到数据
  • t表被锁定写时,会话2不能查到数据

  • 查看是否有表锁:有表锁

如果还是理解不了,再次附上锁的兼容关系图,跟着实验再走一遍就好了

最后最后
不要再把“如果xxx字段上没有索引,那么行锁将上升为表锁”中的表锁理解为表级锁了!
表级锁和全表锁的实现方式是完全不同的!

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论