软件开发进阶技能之数据库进阶(三)

简介: 教程来源 https://qcycj.cn/ 本节深入解析MySQL事务与并发控制:涵盖ACID特性(原子性、一致性、隔离性、持久性)及日志/锁/MVCC实现机制;详解四种隔离级别与脏读、不可重复读、幻读问题;剖析MVCC快照读原理、Read View生成策略;介绍行锁、间隙锁、Next-Key Lock等锁类型及死锁处理;最后给出应用层事务最佳实践。

第三部分:事务与并发控制 —— 数据一致性的守护者

当多个用户同时读写数据库时,必须保证数据的一致性,事务和锁机制就是为此设计的。

3.1 事务的 ACID 特性回顾
原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败回滚。

一致性(Consistency):事务执行前后,数据库从一个一致状态变为另一个一致状态(完整性约束未被破坏)。

隔离性(Isolation):并发执行的事务之间互不干扰。

持久性(Durability):事务一旦提交,其结果永久保存(即使系统崩溃)。

数据库通过 日志(Redo Log 保证持久性,Undo Log 保证原子性和回滚)和 锁+MVCC(保证隔离性)来实现 ACID。

3.2 隔离级别与现象
SQL 标准定义了四种隔离级别,从低到高:
image.png
三种并发问题的解释:

脏读:一个事务读取了另一个未提交事务修改的数据。如果后者回滚,读到的就是无效数据。

不可重复读:同一事务内两次读取同一行数据得到不同结果,因为另一个事务修改并提交了该行。

幻读:同一事务内两次查询返回的记录数量不同,因为另一个事务插入或删除了符合条件的数据。

MySQL InnoDB 默认隔离级别是 REPEATABLE READ,它通过 MVCC(多版本并发控制)+ Next-Key Lock(间隙锁+行锁)解决了幻读问题,实际上达到了接近 SERIALIZABLE 的效果但性能更好。

3.3 MVCC —— 无锁的高并发读
MVCC 是 InnoDB 和 PostgreSQL 等数据库实现高并发的核心机制。其思想是:写操作不阻塞读操作,读操作只读数据的一个快照。

3.3.1 InnoDB 中的 MVCC 实现
InnoDB 为每一行数据增加了两个隐藏字段:

DB_TRX_ID:最后修改该行的事务 ID。

DB_ROLL_PTR:指向 Undo Log 中该行的旧版本链。

当一个事务开始时,会获得一个全局递增的事务 ID。执行 SELECT 时,事务只能看到以下版本的数据:

修改该行的事务 ID 小于当前事务 ID(已提交的)且没有活跃事务修改。

或者修改该行的事务 ID 在当前事务的 Read View 中被标记为已提交。

Read View 是一个数据结构,记录当前系统中所有活跃(未提交)事务的 ID 列表。事务开始时刻生成 Read View(RR 级别下只在第一个 SELECT 时生成,并复用整个事务;RC 级别下每次 SELECT 都重新生成)。

3.3.2 示例解释 MVCC 如何避免不可重复读
假设有行数据初始值为 (id=1, balance=100),trx_id=10。

事务 A(trx_id=20)开始,执行 SELECT balance FROM account WHERE id=1,此时生成 Read View,看到活跃事务无,所以读到 balance=100。

事务 B(trx_id=21)开始,更新 balance=200,并将旧版本(100)写入 Undo Log,新行 trx_id=21。

事务 A 再次 SELECT balance,因 Read View 仍是在事务开始时生成的,事务 21 是活跃事务且大于 Read View 的低水位,所以 A 仍看到旧版本(通过 Undo 链找到版本 trx_id=10),实现了可重复读。

3.4 锁机制:行锁、间隙锁、Next-Key Lock、表锁
InnoDB 支持多粒度锁,其中最重要的是行锁和间隙锁。

3.4.1 行锁(Record Lock)
行锁只锁住索引记录。注意:如果查询没有使用索引,InnoDB 会退化为表锁(实际上是锁住所有行,效率极差)。

3.4.2 间隙锁(Gap Lock)
间隙锁锁定一个范围(两条索引记录之间的间隙),但不包括记录本身。主要用于防止幻读。例如 SELECT * FROM user WHERE id BETWEEN 10 AND 20 FOR UPDATE,会锁住 id 在 (10,20) 之间的间隙,防止其他事务插入 id=15 的新记录。

3.4.3 Next-Key Lock = 行锁 + 间隙锁
InnoDB 在 REPEATABLE READ 级别下执行范围查询时,会使用 Next-Key Lock,锁定记录本身及记录前的间隙,彻底防止幻读。

3.4.4 意向锁(Intention Lock)
表级别的锁,表明事务将要或正在持有行锁。目的是为了在加表锁时快速检测是否有行锁,避免逐行检查。

3.5 死锁的检测与处理
死锁指两个或多个事务互相持有对方需要的锁,导致无限等待。InnoDB 会自动检测死锁(通过等待图),并选择回滚一个事务(通常是更新行数较少的事务),让另一个继续执行。应用程序需要处理好重试逻辑。

死锁示例与避免

-- 事务1
BEGIN;
UPDATE account SET balance=balance-100 WHERE id=1;
UPDATE account SET balance=balance+100 WHERE id=2;
COMMIT;

-- 事务2
BEGIN;
UPDATE account SET balance=balance-50 WHERE id=2;
UPDATE account SET balance=balance+50 WHERE id=1;
COMMIT;

如果两个事务几乎同时执行,事务1锁住了id=1,事务2锁住了id=2,然后各自尝试锁另一个 id,死锁发生。

避免策略:

所有事务按照相同的顺序访问资源(如总是先更新 id=1 再 id=2)。

尽量使用较低的隔离级别(如 RC,没有间隙锁,死锁概率降低)。

控制事务大小,快速提交。

使用 SELECT ... FOR UPDATE 提前锁定需要的行。

3.6 应用层事务最佳实践
尽量缩短事务:不要在一个事务中执行用户输入、远程调用等耗时操作,这些会长时间持有锁,增加死锁风险和并发下降。

避免在事务中进行大规模 SELECT:如果只是读取数据且不要求强一致性,可以在事务外执行。

合理设置超时:innodb_lock_wait_timeout 控制行锁等待时间,避免个别事务阻塞整个系统。
来源:
https://fndvx.cn/

相关文章
|
27天前
|
XML 前端开发 程序员
初级程序员必备的十大技能之 API 接口与前后端联调(一)
教程来源 http://qeext.cn/ 本文系统讲解API设计规范(RESTful/GraphQL)、HTTP协议核心(方法、状态码、头信息)、前后端联调流程及调试工具,助你打造标准化、高可用接口,打破前后端协作孤岛。
|
27天前
|
存储 程序员 Linux
初级程序员必备的十大技能之 Git 版本控制(一)
教程来源 http://xcfsr.cn Git是程序员的“后悔药”与“时光机”:可随时回退错误修改、隔离并行开发、一键恢复稳定版本。作为分布式版本控制系统,它本地全量存储、离线可用、安全可靠,支撑全球90%以上团队高效协作。
|
23小时前
|
Ubuntu Linux KVM
虚拟机搭建教程(二)
教程来源 https://zlpow.cn/ 本文详解Windows、Linux三大平台虚拟化实战:Windows下用VMware安装Ubuntu 24.04(含Tools与快照),VirtualBox部署CentOS Stream 9;Linux主机通过KVM命令行及virt-manager搭建高性能虚拟机,覆盖配置、联网、增强工具与管理全流程。
|
23小时前
|
消息中间件 NoSQL 中间件
软件开发进阶技能之分布式与高并发(二)
教程来源 https://oplhc.cn/ 消息队列(MQ)是分布式系统核心中间件,以异步通信实现服务解耦、流量削峰与最终一致性。支持可靠投递、幂等消费与死信处理,广泛应用于秒杀、日志收集等高并发场景。
|
23小时前
|
缓存 负载均衡 NoSQL
软件开发进阶技能之分布式与高并发(一)
教程来源 https://tmywi.cn/ 本文系统讲解分布式与高并发核心技能:从CAP/BASE理论、负载均衡、多级缓存(穿透/击穿/雪崩应对)、消息队列、分布式事务/锁,到微服务治理与限流熔断,涵盖原理、实战代码与真实场景,助你构建高可用、可扩展的现代系统。
|
23小时前
|
存储 自然语言处理 算法
软件开发新手入门五大核心技能之计算机基础常识(三)
教程来源 http://lemci.cn/ 本章系统讲解数据结构基础:数组(连续存储、O(1)访问)、链表(指针链接、O(1)增删)、栈(LIFO)、队列(FIFO)、哈希表(O(1)查找)、树与图(层次/网络关系),辅以多语言代码实例,揭示高效组织数据的核心逻辑。
|
23小时前
|
存储 Linux KVM
虚拟机使用教程大全(三)
教程来源 https://qcycj.cn/ 快照是虚拟机的“时间胶囊”,可保存任意时刻的完整状态(含内存与磁盘),支持快速回滚、实验保护与克隆部署。本文详解VMware、VirtualBox、KVM三大平台快照创建/恢复/删除操作,强调其非备份本质、性能影响及3–5个快照的黄金管理实践。
|
27天前
|
程序员 开发工具 git
初级程序员必备的十大技能之 Git 版本控制(四)
教程来源 http://fndvx.cn 远程仓库是团队协作核心,涵盖添加/查看/修改/删除远程源、推送拉取代码、追踪分支及处理冲突等关键操作,支撑高效协同开发。
|
23小时前
|
Prometheus 监控 NoSQL
软件开发进阶技能之分布式与高并发(五)
教程来源本节详解高并发秒杀系统设计与可观测性实践:通过CDN静态化、Redis原子扣减、MQ异步下单、唯一键防重等实现抗洪峰、零超卖;并集成Prometheus监控、SkyWalking链路追踪、ELK日志分析,构建完整可观测体系。
|
23小时前
|
缓存 NoSQL 数据库
软件开发进阶技能之数据库进阶(六)
教程来源 https://bncne.cn/ 本节深入探讨NoSQL数据库与混合持久化架构:涵盖Redis高级用法(数据结构、RDB/AOF持久化、Sentinel/Cluster)、MongoDB索引与聚合,以及MySQL+Redis+Elasticsearch+Cassandra的电商混合存储实践,并通过游戏排行榜案例对比三种实现方案,强调性能、一致性与成本的平衡。