MySQL Record Locking 并发更新冲突的流程化处理方案问询
记录锁定与并发更新冲突的解决方案(以地址管理应用为例)
针对你描述的场景,核心问题是悲观锁超时后缺乏有效通知,且提交时未校验数据新鲜度,导致旧数据覆盖新修改。以下是从技术实现到流程规范的完整解决方案:
一、核心机制优化
1. 带超时通知的悲观锁实现
- 后端维护一张
record_locks表,记录record_id、locked_by(用户ID)、expire_at(超时时间戳)。用户进入编辑页时,插入/更新该表的锁定记录,设置合理的超时(比如15分钟,可根据业务场景调整)。 - 前端在编辑页加载后,每隔30秒向后端发起一次请求,校验当前记录的锁定状态:
- 如果锁未超时且属于当前用户,继续允许编辑;
- 如果锁已超时或被其他用户抢占,立刻在界面顶部显示红色警告:「该记录已被其他用户修改或锁定超时,请刷新页面获取最新数据」,同时禁用提交按钮。
- 其他用户进入编辑页时,后端先检查
record_locks:- 锁未超时:直接返回错误提示「该记录正在被用户X编辑,请稍后再试」;
- 锁已超时:允许进入编辑,但强制显示提示「该记录曾被其他用户编辑,当前数据可能过期,请确认后再修改」。
2. 乐观锁兜底(必加机制)
无论悲观锁是否生效,提交时必须通过乐观锁校验数据新鲜度:
- 给
address表添加version字段(整数类型,初始值为1),或last_modified_at字段(时间戳)。 - 用户进入编辑页时,同时获取当前记录的
version值(或last_modified_at)并存在前端。 - 提交更新时,后端执行的SQL需包含版本校验:
UPDATE address SET street = ?, city = ?, version = version + 1 WHERE id = ? AND version = ?; - 如果SQL执行后受影响行数为0,说明记录已被其他用户修改,后端返回冲突错误。前端收到错误后,展示选项:「该记录已被修改,是否查看最新版本?」,提供「查看最新」(刷新页面加载最新数据)和「放弃修改」两个操作。
3. 可选增强:实时冲突推送
如果业务对实时性要求高,可以引入WebSocket:
- 用户提交修改成功后,后端通过WebSocket向所有正在编辑该记录的用户推送消息。
- 前端收到消息后,立刻弹出提示「该记录已被其他用户更新」,并自动刷新页面加载最新数据,避免用户继续基于旧数据操作。
二、流程规范建议
- 编辑触发阶段:
- 用户点击「编辑」按钮时,后端先校验记录锁定状态,未锁定则加锁并返回最新数据+版本号;已锁定且未超时则直接拦截,不进入编辑页。
- 编辑进行阶段:
- 前端定时校验锁定状态,超时或被抢占时立即限制操作,避免无效编辑;
- 后端在锁超时后自动清理
record_locks中的过期记录,释放锁定。
- 提交校验阶段:
- 强制执行乐观锁校验,忽略前端的锁定状态(防止前端篡改或网络延迟导致的状态不一致);
- 冲突发生时,优先引导用户查看最新数据,禁止默认覆盖,让用户自主决策。
- 用户体验优化:
- 锁定超时时间不宜过短(避免用户正常编辑时频繁被打断),也不宜过长(避免长期占用锁);
- 所有状态提示需清晰直白,让用户明确知道当前记录的状态和可执行操作。
内容的提问来源于stack exchange,提问作者user17950319
相关产品推荐
相关产品推荐

