什么是乐观锁(Optimistic Locking)?如何用它解决Concurrent Data Change异常
乐观锁(Optimistic Locking)方案及Concurrent Data Change异常解决方法
什么是乐观锁
乐观锁是一种轻量级的并发控制思路,它假设大部分场景下不会出现并发数据修改冲突,所以不会像悲观锁那样提前对数据加锁(比如用SELECT ... FOR UPDATE)。它的核心逻辑是:在提交数据更新的瞬间,检查这份数据从读取到更新的这段时间里,有没有被其他操作修改过,只有确认没被修改过,才允许更新成功。
常见的实现方式有两种:
- 版本号机制:给数据表加一个
version字段(一般是整数),每次更新数据时,将版本号自增1,更新时会带上之前读取到的版本号,只有数据库中的版本号和这个值匹配,更新才生效。 - 时间戳机制:给数据表加
last_modified字段(存储最后修改时间),更新时对比读取时拿到的时间戳和数据库当前的时间戳是否一致。
如何用乐观锁解决Concurrent Data Change异常
Concurrent Data Change异常本质是多个操作同时修改同一份数据,导致数据覆盖或状态不一致,比如你之前遇到的加载策略到PC时,可能是你读取策略后,其他人同时修改了这份策略,你再提交更新就触发了异常。用乐观锁解决的步骤如下:
1. 改造数据表结构
给存储策略的数据表新增一个版本字段,比如:
ALTER TABLE policy ADD COLUMN version INT DEFAULT 1;
2. 查询数据时携带版本信息
读取策略数据的时候,把版本号一起查出来:
SELECT id, content, version FROM policy WHERE id = ?;
3. 提交更新时校验版本
更新策略数据时,在WHERE条件中带上之前读取到的版本号,同时将版本号自增:
UPDATE policy SET content = ?, version = version + 1 WHERE id = ? AND version = ?;
4. 处理更新结果
执行更新语句后,检查数据库返回的影响行数:
- 如果影响行数为1,说明更新成功,数据没有被并发修改;
- 如果影响行数为0,说明这段时间内数据已经被其他操作修改了,此时需要抛出异常或者提示用户重新加载最新的策略后再尝试操作。
针对加载策略场景的具体处理
在你之前的加载策略到PC的场景中,可以这么优化:
- 当用户触发加载策略操作时,不仅加载策略内容,同时记录下当前的版本号;
- 当用户修改完策略准备提交时,用上述带版本校验的更新语句执行操作;
- 如果更新失败(影响行数为0),直接提示用户“当前策略已被其他人修改,请重新加载最新版本后再操作”,避免触发Concurrent Data Change异常。
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

