导读:本期聚焦于梁博渊创作的《PostgreSQL并发控制中乐观锁与悲观锁该如何实现与选择?》,敬请观看详情。当两个事务同时修改同一行数据时,数据库该怎样避免丢失更新?PostgreSQL提供了悲观锁与乐观锁两类思路。悲观锁依赖SELECT FOR UPDATE在读取时就加锁,阻塞其他写操作;乐观锁则借助版本号或时间戳,在提交时校验冲突。二者在吞吐量、响应延迟和代码复杂度上差异明显。理解MVCC底层机制有助于判断高并发下单号扣减、库存变更等场景该用哪种策略,以及如何通过合理索引降低锁等待。

在PostgreSQL这类支持多版本并发控制(MVCC)的关系型数据库中,多个会话同时读写同一批数据是十分常见的运行态。若缺乏恰当的并发控制手段,就会出现丢失更新、脏读或不可重复读等问题。乐观锁与悲观锁是两种截然不同的冲突解决哲学,前者假设冲突很少发生、只在提交时校验,后者假设冲突频繁、在读取阶段就阻断竞争者。实际系统中并不能笼统地说谁更好,而要结合业务容忍度、请求峰值与数据热点分布来落地。

PostgreSQL并发控制中乐观锁与悲观锁该如何实现与选择?

悲观锁的实现机制与代码示例

悲观锁的核心思想是“先取锁再操作”。在PostgreSQL中,最典型的做法是使用SELECT ... FOR UPDATE语句,它会在读取目标行时为其加上行级排他锁,使其他事务对该行的UPDATEDELETE以及加锁读取都被阻塞,直到当前事务提交或回滚。这种机制建立在MVCC之上,并没有改变多版本快照读的特性,只是额外引入了锁等待队列。

下面是一段在库存扣减场景中使用的悲观锁示例。事务开启后,先锁定商品库存行,再执行扣减,最后提交。由于锁的存在,并发的两个请求不会同时读到相同的剩余量,从而避免了超卖。

BEGIN;
SELECT stock FROM products WHERE id = 1001 FOR UPDATE;
-- 假设查到 stock = 10
UPDATE products SET stock = stock - 1 WHERE id = 1001;
COMMIT;

悲观锁的优点在于逻辑直观、不易出现业务层的并发漏洞,特别适合强一致性要求的金融记账。但其代价是吞吐量受锁等待影响明显,如果热点行被频繁修改,大量会话会堆积在锁上,甚至引发死锁。因此在高并发秒杀场景中,往往需要配合应用层排队或分桶扣减来缓冲突。

乐观锁的版本号方案与冲突处理

乐观锁并不在读取时加锁,而是为每行数据引入一个版本标记,常见做法是增加version整数字段或updated_at时间戳。更新时通过WHERE子句带上旧版本值,若影响行数为零,说明期间已被其他事务改动,当前提交应视为冲突失败,由应用决定重试或报错。

以下示例展示了基于版本号的乐观锁更新。第一次读取得到版本为3,提交更新时要求版本仍为3,若成功则版本变为4;若失败则应用捕获异常并重试读取新值。

-- 读取时获取版本
SELECT id, stock, version FROM products WHERE id = 1001;
-- 假设 version = 3, stock = 10
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 1001 AND version = 3;
-- 若返回影响行数 0,表示冲突

乐观锁在冲突率低的系统中表现优异,因为它避免了锁等待,读操作完全无阻塞。但当写竞争剧烈时,大量更新会失败并重试,反而浪费资源。此外,乐观锁要求业务代码显式处理冲突分支,增加了上层逻辑的复杂度,且必须保证version字段在所有更新路径中被正确维护。

基于MVCC原理的锁选择策略

要合理选型,需理解PostgreSQL的MVCC如何隔离事务。默认隔离级别下,读不阻塞写、写不阻塞读,快照保证了一致性视图。悲观锁的FOR UPDATE实际上是在此之上叠加了物理锁,用来强制串行化特定行的修改;乐观锁则完全利用快照读加条件写,依赖原子更新检测冲突。

从实践角度看,若业务操作耗时长、涉及多表联动且不能接受重试,悲观锁更稳妥;若请求简短、冲突少、需要高吞吐,乐观锁更轻量。还可以混合使用,例如读取用快照、关键提交用条件更新。下表归纳了二者差异:

维度悲观锁乐观锁
加锁时机读取阶段提交阶段
冲突表现等待或死锁更新失败重试
适用场景强一致、低并发高并发、弱冲突

在真实架构中,还应关注索引对锁范围的影响。没有命中索引的UPDATEFOR UPDATE会升级为表级扫描并锁住更多行,因此必须为并发字段建立合理索引。同时,将大事务拆小、控制锁持有时间,是无论哪种锁都适用的优化原则。

PostgreSQL乐观锁悲观锁修改时间:2026-08-17 04:10:23

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。