总结sqlserver的使用,总是会回想起很多开发过程当中加班努(拼)力(命)的场景,今天,就把之前一个由于数据库脏读到这的OA系统员工请假流程状态不一致问题和解决思路分享一下。
业务场景描述
由于企业项目原因,这里对业务细节进行了模糊,还请各位大佬担待。
1. 业务背景
某企业OA系统正在处理年度高峰期的大量请假申请,人力资源部门同时有多个审批人员在处理请假流程。系统使用SQL Server 2022作为数据库,部分报表查询使用了WITH(NOLOCK)
提示以提高性能。
2. 脏读发生过程
时间线:
-
09:00:00 - 员工A提交请假申请(初始状态:
待审批
)INSERT INTO LeaveRequests (EmployeeID, StartDate, EndDate, Status) VALUES (1001, '2023-12-25', '2023-12-28', 'Pending')
-
09:00:05 - 审批人B开始审批该申请(事务1)
BEGIN TRANSACTION UPDATE LeaveRequests SET Status = 'Approving' -- 状态变为"审批中" WHERE RequestID = 2345 -- 尚未提交,审批人正在核对日历
-
09:00:10 - 员工A同时查询申请状态(事务2,使用NOLOCK)
-- 员工客户端执行的查询 SELECT Status FROM LeaveRequests WITH(NOLOCK) WHERE RequestID = 2345 -- 返回结果:"Approving"
-
09:00:15 - 审批人B发现冲突,回滚审批
ROLLBACK TRANSACTION -- 状态回滚到"Pending"
-
09:00:20 - 员工A看到系统显示"已开始审批",于是取消出差计划
-
但实际申请仍处于"待审批"状态
-
导致员工错误决策
-
3. 业务影响分析
影响维度 | 具体表现 |
---|---|
数据一致性 | 员工看到不存在的中途状态 |
业务流程 | 基于错误状态的业务决策 |
用户信任度 | 对系统可靠性产生怀疑 |
法律风险 | 若涉及薪资计算可能引发纠纷 |
4. 相关数据表结构
CREATE TABLE LeaveRequests ( RequestID INT PRIMARY KEY IDENTITY, EmployeeID INT NOT NULL, StartDate DATE NOT NULL, EndDate DATE NOT NULL, Status VARCHAR(20) NOT NULL CHECK (Status IN ('Pending', 'App