如何在MySQL中模拟高并发场景下的行锁升级现象?

酷静同学_9157

酷静同学_9157

2026-06-12

845人浏览

原创

mysql行锁不会主动升级为表锁,所谓“升级”实为未走索引导致全表扫描并逐行加x锁;核心在于执行计划是否命中索引,而非sql字面意图。

如何在mysql中模拟高并发场景下的行锁升级现象?

MySQL中行锁不会“主动升级”为表锁,所谓“升级”其实是因查询未走索引导致全表扫描,InnoDB被迫对所有聚簇索引记录加X锁——效果等同于表锁,但底层仍是行锁机制。模拟的关键不是写个LOCK TABLES,而是制造「本想锁一行、实际锁全表」的错觉。

用无索引条件触发全表扫描加锁

这是最常见也最容易复现的“伪升级”场景。InnoDB只在通过索引定位时才加精确行锁;一旦WHERE条件无法命中索引(或索引失效),就会遍历所有行并逐个加X锁。

  • 建表时确保目标字段没索引:CREATE TABLE t_lock (id INT PRIMARY KEY, name VARCHAR(20));
  • 插入10条以上数据,比如INSERT INTO t_lock VALUES (1,'a'),(2,'b'),...,(10,'j');
  • 客户端A执行:BEGIN; UPDATE t_lock SET name='x' WHERE name='a'; —— 因name无索引,InnoDB会对全部10行加X锁
  • 客户端B立刻执行:UPDATE t_lock SET name='y' WHERE id=5; —— 会被阻塞,即使id是主键索引,因为全表X锁已存在

用隐式类型转换让索引失效

字段类型和查询值类型不一致时,MySQL会做隐式转换,导致索引无法使用,进而触发全表扫描加锁。这种场景在业务中极隐蔽,但复现成本极低。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • 假设name字段是VARCHAR,但查询时传了数字:UPDATE t_lock SET name='z' WHERE name=123;
  • MySQL会把每行name转成数字再比对(如'abc'→0),无法用索引
  • 即使你后来给name加了索引,这条语句依然全表加锁
  • 验证方式:执行前先看EXPLAIN SELECT * FROM t_lock WHERE name=123;,如果type是ALL,就稳了

用SELECT ... FOR UPDATE配合非索引条件观察阻塞链

相比UPDATE,显式加锁更利于观察锁行为,且能避免事务自动提交干扰。

  • 客户端A:BEGIN; SELECT * FROM t_lock WHERE name='a' FOR UPDATE;(name无索引)
  • 此时InnoDB已对所有行加X锁,但尚未修改数据,锁状态更“干净”
  • 客户端B执行任何涉及t_lock的写操作(如INSERT、UPDATE、DELETE)都会被阻塞
  • 用SHOW ENGINE INNODB STATUS\G查TRANSACTIONS部分,能看到lock struct(s)数量远超1行

为什么LOCK TABLES不是正解?

手动执行LOCK TABLES t_lock WRITE;确实能锁整张表,但它和InnoDB行锁机制无关,属于Server层表锁,会阻塞所有并发读(包括SELECT),且与事务隔离级别无关。真实业务中几乎不用,也不反映InnoDB的锁行为逻辑。

  • LOCK TABLES后,其他连接连SELECT * FROM t_lock都会被挂起,而“伪升级”下普通SELECT仍可读(除非加FOR UPDATE)
  • InnoDB内部没有“升级开关”,只有“是否能走索引”这一判断依据
  • 真正影响锁范围的,是WHERE条件能否命中索引,而不是事务里操作了多少行

最易被忽略的一点:锁范围取决于**执行计划**,而非SQL字面意思。哪怕你只更新1行,只要优化器选了全表扫描,就等于锁了全部。所以模拟前务必用EXPLAIN确认索引是否真的生效。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

2233

6

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.21

1379

5

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

795

5

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.19

3092

5

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.25

5228

4

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.08

1159

3

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

5471

4

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

2023.08.14

4802

7

mysql事务隔离级别
mysql事务隔离级别

mysql规范中定义了四种事务隔离级别,不同的隔离级别对事务的处理有所不同。本专题为大家提供mysql事务隔离级别相关的文章内容,大家可以免费体验。

2023.08.16

6374

11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 187人学习