一、前言
高并发场景下多个请求同时修改同一行数据,若无并发控制机制,会出现数据覆盖、状态错乱、统计数值不准、库存超卖等脏数据问题。 关系型数据库提供两套原生并发控制方案:悲观锁、乐观锁,二者设计思路完全相反,适配不同并发争抢场景。除此之外,嵌入式数据库、分布式集群还有专属锁实现方案,下文一并完整拆解。
并发锁是一类并发控制机制的统称。在多线程、多进程、多服务并发场景下,多个请求同时读写同一份共享数据时,用来协调访问顺序、防止并发修改造成脏数据、数据覆盖、状态错乱的方案。
后端开发中常见实现方案包含:悲观锁、乐观锁、SQLite 操作系统文件锁、Redis 分布式锁。 不同锁底层实现、生效范围、并发能力差异巨大,需要结合部署架构(单机 / 分布式)、业务并发压力选型。
二、悲观锁(强一致性锁)
2.1 核心设计思想
默认并发一定会产生资源冲突,操作数据前先主动锁定目标资源,整个事务全程持有锁,事务提交 / 回滚后才释放;其余请求必须阻塞排队,等待锁释放后才能操作数据。
2.2 核心特点
2.3 基础 SQL 示例
— 开启事务并对目标行加悲观行锁
BEGIN;
SELECT * FROM table WHERE id = 1 FOR UPDATE;
— 执行更新逻辑
UPDATE table SET num = num – 1 WHERE id = 1;
COMMIT;
2.4 适用场景
高并发写入、资源争抢频率极高、零脏数据容忍的核心流程:库存扣减、资金交易、订单核销、账务结算等业务。
三、乐观锁(高性能无阻塞锁)
3.1 核心设计思想
默认日常并发冲突极少,不提前上锁,直接执行业务查询与更新逻辑;更新操作前通过版本号 version、更新时间戳 update_time 校验当前数据是否被其他请求修改,校验失败则判定冲突,执行放弃或重试逻辑。
3.2 核心特点
3.3 通用实现 SQL 模板
1.建表增加版本字段
CREATE TABLE demo(
id INT PRIMARY KEY,
count INT,
version INT DEFAULT 0
);
2.更新时校验版本
UPDATE demo
SET count = count – 1, version = version + 1
WHERE id = 1 AND version = 1;
执行后判断受影响行数,等于 0 代表数据已被其他线程修改,触发冲突重试。
3.4 适用场景
低并发修改、读多写少业务:基础信息修改、普通表单更新、静态统计数据录入、配置更新等冲突概率极低的场景。
四、悲观锁 vs 乐观锁完整对比表
| 执行逻辑 | 先上锁、后操作、事务结束释放锁 | 先查询操作、更新前校验版本,冲突重试 |
| 并发性能 | 低,高争抢场景大量请求阻塞排队 | 高,全程无锁阻塞 |
| 数据安全能力 | 极高,完全避免并发数据覆盖 | 较高,依赖版本字段校验兜底 |
| 数据库资源开销 | 高,长期占用行锁资源 | 极低,仅普通条件判断 |
| 高频争抢场景适配 | 适合,无无限重试损耗 | 不适合,大量冲突重试消耗 CPU |
| 事务依赖 | 强依赖事务,锁生命周期绑定事务 | 不强制依赖完整事务,单条 UPDATE 即可实现 |
五、SQLite 专属操作系统文件锁
前面两种锁均基于服务型数据库行锁,嵌入式 SQLite 无行锁、表锁能力,底层依靠操作系统文件锁实现并发隔离,属于特殊锁机制。
底层原理 SQLite 数据库为单一磁盘文件,区分两种文件锁:共享锁(读)、排他锁(写)。
1.读请求:加共享锁,多进程可同时读取;
写请求:加排他锁,同一时间全局仅允许一个写入操作。
即使开启 WAL 读写分离优化,也只能做到读写不互斥,写入操作依旧串行执行
2.致命缺陷
- 仅支持单机本地文件,NFS、SMB 共享磁盘下文件锁失效,直接造成数据错乱;
- 多进程高频写入频繁抛出 database is locked 锁超时异常;
- 锁粒度是整个数据库文件,无法精准锁定单行数据。
3.通用规避方案 开启 WAL 模式、延长 busy_timeout 锁等待时间、批量合并写入、上层增加写入重试逻辑;多服务共用 SQLite 文件架构不推荐长期使用。
六、Redis 分布式锁(跨机器集群专用)
悲观锁、乐观锁、SQLite 文件锁全部仅在单台服务器、单个数据库实例内生效;微服务、多节点分布式架构下,需要全局锁控制并发,此时采用 Redis 分布式锁。
1.实现核心原理 利用 Redis 单命令原子性抢占锁:SET lock_key unique_id NX EX 30
- NX:key 不存在时才创建,代表抢占锁成功;
- EX:设置锁自动过期时间,防止进程崩溃永久死锁;
- unique_id:客户端唯一标识,避免释放其他线程的锁。
2.优势与短板
- 优势:跨服务器、跨服务全局互斥,适配分布式集群高并发场景;
- 短板:依赖 Redis 服务可用性,需要处理主从切换丢锁、任务未完成锁过期等边界问题。
3.适用场景 多实例微服务、多服务器部署、定时任务防重复执行、分布式库存扣减等单机锁无法覆盖的场景。
| 生效范围 | 单机数据库实例内 | 单机数据库实例内 | 仅限单台本机 | ✅ 跨机器、分布式集群 |
| 锁粒度 | 行级 / 表级 | 逻辑行级(业务层) | 整库文件 | 自定义业务 Key |
| 阻塞特性 | 阻塞等待,争抢会排队 | 无阻塞,冲突后重试 | 写操作全局串行阻塞 | 抢占模式,抢不到可重试 |
| 并发写入上限 | 较高(行锁互不干扰) | 高(冲突依赖重试) | 很低,同一时刻只能一个写 | 高,全局互斥 |
| 依赖组件 | MySQL/PostgreSQL | 任意关系数据库 | SQLite + OS 文件锁 | Redis 服务 |
| 典型缺陷 | 长事务易引发锁等待、死锁 | 超高并发场景大量重试消耗 CPU | 共享盘 (NFS/SMB) 锁失效、频繁database is locked | 需要处理锁过期、主从切换丢锁、防误释放 |
| 典型适用场景 | 单机核心交易、库存、资金业务 | 读多写少、配置、普通表单更新 | 单机小型工具、低并发本地存储 | 微服务、多服务器集群、定时任务防重复 |
七、落地选型完整判断标准
八、总结
并发锁是统称,用来解决多请求同时修改共享资源引发的数据冲突;根据单机、分布式场景,衍生出悲观锁、乐观锁、文件锁、分布式锁多种实现。
网硕互联帮助中心





评论前必须登录!
注册