news 2026/4/23 22:06:04

锁产生原理、脏读、不可重复读、幻读、丢失更新

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
锁产生原理、脏读、不可重复读、幻读、丢失更新

时序过程 + 完整可直接复制运行的 MySQL 语句,包含:锁产生原理、脏读、不可重复读、幻读、丢失更新,每一步你开两个会话窗口跟着执行就能亲眼复现,同时讲清并发测试为什么会压出锁、脏数据。基于 MySQL InnoDB,默认引擎。

前置准备

先建测试表,所有语句直接复制执行:

sql

CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), money INT COMMENT '余额' ); INSERT INTO account(name,money) VALUES ('张三',100);

操作要求打开 MySQL 两个客户端窗口:会话 A、会话 B,分开执行,模拟两个并发事务。


一、并发为什么会产生锁(悲观锁、行锁、阻塞演示)

原理回顾

多个事务同时修改同一行数据,InnoDB 自动加X 排他行锁

  • 持有锁的事务:可以读写
  • 其他事务:阻塞等待,直到锁释放并发线程越多,锁等待越长、锁竞争越严重,压测就会出现锁超时、接口卡顿、TPS 上不去

复现演示

会话 A

sql

BEGIN; -- 加排他行锁,锁定张三这一行 SELECT * FROM account WHERE id=1 FOR UPDATE;

此时:id=1 这一行已经被上锁

会话 B(立刻执行)

sql

BEGIN; UPDATE account SET money=50 WHERE id=1;

现象:会话 B 直接卡住阻塞,无法执行原因:行锁被 A 占用,写操作必须等待锁释放。

回到会话 A 释放锁

sql

COMMIT;

A 提交后,锁释放,会话 B 立刻继续执行完成

并发压测结论

JMeter 几百线程同时 update 同一行 → 大量锁等待队列 → 数据库耗时飙升无索引 update 会直接锁整张表(表锁),整个表全部阻塞,服务雪崩。


二、脏读 Dirty Read(最经典脏数据)

定义

事务 A 修改数据未提交,事务 B 读到了;之后 A 回滚,B 读到的数据就是无效脏数据

MySQL 隔离级别控制

  • 读未提交READ UNCOMMITTED会出现脏读
  • 读已提交 / 可重复读:禁止脏读

完整复现步骤

第一步:先修改全局隔离级别(会话单独设置)

会话 A、会话 B 都执行

sql

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

会话 A

sql

BEGIN; -- 张三余额 100 -> 200,**未提交** UPDATE account SET money=200 WHERE id=1;

会话 B(立刻查询)

sql

BEGIN; SELECT * FROM account WHERE id=1;

结果:查到 money=200

重点:A 还没提交,B 已经读到修改后数据,这就是脏读

会话 A 回滚(放弃修改)

sql

ROLLBACK;

张三余额恢复为100

会话 B 再次查询

sql

SELECT * FROM account WHERE id=1;

余额变回 100。结论:B 之前读到的 200,就是不存在的脏数据


三、不可重复读 Non-repeatable Read

定义

同一个事务内,多次查询同一行,结果不一样原因:其他事务中途更新并提交了该行数据侧重:行数据被修改隔离级别:

  • READ UNCOMMITTED、READ COMMITTED 会出现
  • RR 可重复读:解决不可重复读

复现步骤

两会话先设置隔离级别

sql

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

会话 B

sql

BEGIN; -- 第一次查询 SELECT * FROM account WHERE id=1;

查到:money=100

会话 A

sql

BEGIN; UPDATE account SET money=150 WHERE id=1; COMMIT;

A 修改并直接提交

会话 B(同一个事务内,再次查询)

sql

SELECT * FROM account WHERE id=1;

查到:money=150

现象:同一个事务 B,两次查询同一行结果不同→不可重复读


四、幻读 Phantom Read

定义

同一个事务内,前后查询记录总数不一样原因:其他事务插入 / 删除数据并提交,行数凭空增减,像幻觉侧重:数据条数变化MySQL InnoDB 默认 RR 级别基本解决幻读,间隙锁防插入

先新增测试语句

sql

TRUNCATE account; INSERT INTO account(name,money) VALUES ('张三',100),('李四',200);

设置隔离级别

sql

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

会话 B

sql

BEGIN; -- 第一次统计总数 SELECT COUNT(*) FROM account;

结果:2

会话 A

sql

BEGIN; INSERT INTO account(name,money) VALUES ('王五',300); COMMIT;

插入新数据并提交

会话 B(同事务再次查询总数)

sql

SELECT COUNT(*) FROM account;

结果:3

现象:同个事务,前后条数不一样 →幻读


五、丢失更新(业务最严重脏数据,并发压测必现)

这是接口并发 BUG、库存超卖、重复扣款的根源,所有隔离级别都防不住,必须加锁 / 乐观锁解决。

场景

张三余额:100线程 A、线程 B 同时扣 50,理想最终余额:0不加锁并发执行后结果:50(丢失一次更新)

复现时序全过程

  1. 会话 A

sql

BEGIN; SELECT money FROM account WHERE id=1; -- 读到 100
  1. 几乎同时会话 B

sql

BEGIN; SELECT money FROM account WHERE id=1; -- 同样读到 100
  1. 会话 A 计算:100-50=50,更新

sql

UPDATE account SET money=50 WHERE id=1;
  1. 会话 B 同样计算:100-50=50,更新

sql

UPDATE account SET money=50 WHERE id=1; COMMIT;
  1. 会话 A 提交

sql

COMMIT;

最终结果余额 = 50,第二次扣款直接被覆盖丢失这就是生产最致命的脏数据、并发覆盖问题


六、面试精简背诵版(直接背)

  1. 并发为什么产生锁?多事务同时修改同一行数据,InnoDB 为保证数据安全自动加排他行锁;并发越高锁竞争越激烈,无索引会升级表锁,进而锁等待、死锁、接口超时。

  2. 脏读A 修改未提交,B 读到;A 回滚,B 数据作废。

  3. 不可重复读同事务多次查同一行,中途别人修改提交,前后结果不一致。

  4. 幻读同事务统计数量,中途别人插入删除,条数变化。

  5. 丢失更新多线程同时读取旧值,各自计算更新,后续覆盖前面修改,数据异常。

  6. 隔离级别对应问题

  • 读未提交:脏读、不可重复读、幻读 全有
  • 读已提交:无脏读,有不可重复读、幻读
  • 可重复读 (MySQL 默认):无脏读、无不可重复读,间隙锁基本解决幻读
  • 串行化:全部问题解决,但并发极差
  1. 解决方案悲观锁for update、乐观锁 version 版本号、Redis 分布式锁、缩短事务、加索引避免表锁、接口幂等。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 22:04:28

如何快速成为开源社区贡献者:Awesome-Selfhosted入门完全指南

如何快速成为开源社区贡献者:Awesome-Selfhosted入门完全指南 【免费下载链接】awesome-selfhosted A list of Free Software network services and web applications which can be hosted on your own servers 项目地址: https://gitcode.com/GitHub_Trending/aw…

作者头像 李华
网站建设 2026/4/23 22:04:18

大型集团管控型OA协同平台:从需求到落地的完整拆解(PPT)

本文约9500字,系统梳理大型集团管控型OA协同平台的建设逻辑、核心模块与落地方法论,适合企业CIO、数字化负责人、IT架构师深度阅读。写在前面:为什么集团OA是一门"高难度"生意 OA系统做了几十年,市面上产品一抓一大把。…

作者头像 李华
网站建设 2026/4/23 21:59:56

终极安全指南:如何通过Khoj的魔法链接认证守护你的AI知识库

终极安全指南:如何通过Khoj的魔法链接认证守护你的AI知识库 【免费下载链接】khoj Your AI second brain. Self-hostable. Get answers from the web or your docs. Build custom agents, schedule automations, do deep research. Turn any online or local LLM in…

作者头像 李华
网站建设 2026/4/23 21:57:18

告别卡顿:Svelte 5中$derived与Map类型Store的终极响应式优化指南

告别卡顿:Svelte 5中$derived与Map类型Store的终极响应式优化指南 【免费下载链接】svelte web development for the rest of us 项目地址: https://gitcode.com/GitHub_Trending/sv/svelte Svelte 5作为一款革新性的前端框架,通过其独特的编译时…

作者头像 李华