当前位置:首页 > 技术 > 正文内容

深入解析乐观锁与悲观锁的实现机制

访客 技术 2026年6月30日 2

并发控制中的核心策略:乐观锁与悲观锁

在现代数据库系统中,多个事务同时访问同一数据是常见场景。为了保障事务的隔离性、一致性和数据完整性,并发控制机制显得尤为重要。其中,乐观锁(Optimistic Locking)和悲观锁(Pessimistic Locking)作为两种主流的并发处理思想,被广泛应用于各类数据存储系统中,不仅限于传统关系型数据库,也包括缓存中间件如Redis、Hibernate ORM框架等。

这两种策略本质上是一种设计哲学,而非具体的锁定技术。它们可以根据业务对冲突概率和性能要求的不同进行选择。理解其原理有助于构建高并发、高可用的应用系统。

悲观锁:先锁后操作的安全模式

悲观锁假设在多事务环境下,数据冲突发生的可能性较高,因此在整个数据处理过程中,提前对资源加锁以防止其他事务干扰。这种"先获取锁,再执行操作"的方式确保了数据访问的排他性。

在数据库层面,例如MySQL的InnoDB引擎,悲观锁通常通过SELECT ... FOR UPDATE语句实现。该语句会对查询结果集中的行施加排他锁,阻止其他事务对该部分数据进行修改或再次加锁,直到当前事务提交或回滚。

使用悲观锁时需注意以下几点:

  • 必须关闭自动提交模式(SET autocommit = 0),否则锁会在语句执行后立即释放。
  • 加锁操作应位于事务块内,确保锁的有效范围覆盖整个业务逻辑流程。
  • InnoDB默认使用行级锁,但前提是查询条件涉及索引列;若未命中索引,则会升级为表级锁,极大影响并发性能。

示例流程如下:

BEGIN;
-- 加载商品信息并加排他锁
SELECT status, version FROM inventory WHERE item_id = 1001 FOR UPDATE;
-- 创建订单
INSERT INTO orders (item_id, quantity) VALUES (1001, 1);
-- 更新库存状态
UPDATE inventory SET status = 'locked' WHERE item_id = 1001;
COMMIT;

在此期间,任何试图访问item_id=1001的事务都将被阻塞,直至当前事务结束。

优点: 数据安全性高,适用于写操作频繁且冲突概率大的场景。
缺点: 增加系统开销,可能导致锁等待、死锁问题,降低整体并发吞吐量;对于读多写少的场景则显得过于保守。

乐观锁:无锁化设计的高效方案

与悲观锁相反,乐观锁假定大多数情况下不会发生数据竞争,因此不采用实时加锁机制。它允许事务自由读取和修改数据,在提交更新时才验证数据是否已被其他事务更改。如果检测到冲突,则拒绝本次更新,通常由应用层决定重试或报错。

最常见的实现方式是基于版本号(Version Number)或时间戳(Timestamp)。每次数据更新时,版本字段递增。提交更新前,比较当前数据库中的版本与读取时记录的版本是否一致,仅当一致时才执行修改。

典型SQL实现如下:

-- 第一步:读取数据及版本
SELECT quantity, version FROM inventory WHERE item_id = 1001;

-- 应用层处理逻辑...

-- 第二步:带版本校验的更新
UPDATE inventory 
SET quantity = 99, version = version + 1 
WHERE item_id = 1001 AND version = 5;

若影响行数为0,说明版本已变更,即存在并发修改,需由应用程序处理冲突。

另一种实现方式是使用时间戳字段:

UPDATE inventory 
SET quantity = 99, updated_at = NOW() 
WHERE item_id = 1001 AND updated_at = '2025-04-05 10:00:00';

优点: 避免了锁机制带来的开销,提升了系统的并发能力,尤其适合读多写少的业务场景。
缺点: 冲突发生时需要回滚或重试,增加了应用复杂度;在高并发写入场景下可能引发大量失败更新,影响用户体验。

如何选择合适的并发控制策略?

选择乐观锁还是悲观锁,关键在于评估业务场景下的数据竞争频率和系统性能需求:

  • 使用悲观锁:适用于金融交易、库存扣减等强一致性要求高、冲突频繁的操作。
  • 使用乐观锁:适用于社交点赞、文章浏览量统计等冲突较少、追求高性能的场景。

此外,一些分布式系统还会结合两者优势,采用混合策略。例如,在本地缓存中使用乐观机制,在持久化阶段引入轻量级锁控制。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。