做了个功能,用户可以审核用户发布的数据。其中有个内容状态字段status,如下:
/// <summary>
/// 状态,<=0:审核中,1:己审核成功,可以正常浏览,2:己删除
/// </summary>
public int status { get; set; }
因为默认在添加内容时status=-2,需要经过审核。然后有一个审核页面,从数据库随机取一条status<=0的数据,上面有二个按钮,一个通过,一个不通过,如果点击同意则status+1,不同意则-1,直到status=1就审核通过,就可以在前台页面查看相关内容了。(类似糗百的审核,所有用户都可以参与审核)
下面是我的数据层代码:
public int Update(long contetnid, int status)
{
return SqlHelper.ExecuteNonQuery("update qb_content set status=@status+status where contentid=@contentid",
new SqlParameter("@status", status),
new SqlParameter("@contentid", contetnid));
}
现在碰到一个问题, 如果碰到多个用户同时在审核同一个内容时发生的问题,如当前内容的status=0,而正好有二个用户的审核界面都是这条内容,二个用户都点了通过,那status就直接等于2了,直接变成删除状态了。
这种情况怎么避免?
SqlHelper.ExecuteNonQuery("update qb_content set status=@status+status where contentid=@contentid")
你如果有看过LINQ TO SQL生成的Update语句,就会发现他是类似这样的
Update qb_content set status=@statu+staus where contentid=@contentid and status=@statu
就是说Update的时候检查数据行是否自己读到的状态,如果不是,就不作更新。
采用以上方法,甲、乙两个人只有一个能更新成功。
百度“乐观锁和悲观锁”
具体到你这个问题我觉得就是不要status=@status+status而是status等于一个固定值枚举值,这个枚举值放在程序里
我感觉设计有问题,删除应该单独用一个字段,然后
status < =0 审核
status >0 通过
或者status == int.Max 是删除
update top(1) status = 1 where id = @id and status = 0
这个是典型的并发场景。多个用户同时审核同一内容,必然存在同一资源争用的问题,加锁把其他用户踢掉。
加锁,加条件。