为了解决我的问题,我有一个非常基本的银行系统。目前的过程是:
因此,例如,如果字段为10并且我得到两个更新(10,-5),则字段需要为15(10 + 10 - 5),不仅仅是更新值的情况,它需要做一些算术。
现在我不太清楚如何处理余额的更新,因为可能会有很多请求进来,因此需要相应更新。
我认为一种方法是在SQL端而不是Web作业上进行更新,但这对并发更新没有帮助。
我可以使用该字段进行锁定吗?但是,由于更新已在进行中,因此阻止更新会发生什么?是等待还是失败?如果它等待,那么这应该没问题。我使用的是EF。
我认为另一种方法是让另一个WebJob按计划运行,并将所有金额相加并更新一次值,因此这将是触及该字段的唯一内容。
由于
答案 0 :(得分:0)
无论如何,您需要序列化对帐户余额字段的写入权限(实际上是整行) 如果在您的系统上写入比读取更频繁,或者您不必总是返回最近的余额,那么单独的作业会选择“挂起”插入,并最终更新余额。否则,要获得当前余额,您需要执行类似
的操作SELECT balance +
ISNULL((SELECT SUM(transaction_amount)
FROM pending_insert pi WHERE pi.user_id = ac.user_id
),0) as actual_balance
FROM account ac
WHERE ac.user_id = :user_id
从性能角度来看,这肯定是更昂贵的,但对于某些系统来说,它非常好。另一个陷阱(再次,它可能与您的案例相关或不相关)是强制执行,例如,非负余额。
或者,您可以通过以下方式持续处理银行交易:
提交/回滚
如果涉及多个用户帐户,则必须始终按相同顺序锁定它们以避免死锁。
这种方法更强大,但从并发的角度来看可能更糟糕(同样,它取决于应用程序中更新的性质 - 最坏的情况是一个用户的许多并发银行交易,对多个用户的更新将会更新精细)。
最后,值得一提的是,由于您正在使用SQLServer,请注意锁定升级导致的死锁。您可能需要在任何情况下实现一些重试逻辑
答案 1 :(得分:0)
您可能希望在sql中使用参数替换方法。您需要根据您在Web作业中使用的编程语言了解如何执行此操作。
$updateval = -5;
Update dbtable set myvalue = myvalue + $updateval
code example:
int qn = int.Parse(TextBox3.Text)
SqlCommand cmd1 = new SqlCommand("update product set group1 = group1 + @qn where productname = @productname", con);
cmd1.Parameters.Add(new SqlParameter("@productname", TextBox1.Text));
cmd1.Parameters.Add(new SqlParameter("@qn", qn));
然后执行。