数据库Update操作的一些技巧总结
来源:互联网 发布:网络销售代理合同 编辑:程序博客网 时间:2024/04/28 01:13
数据库Update操作的一些技巧总结
问题背景:
在高并发场景下,当多个任务同时操作同一条数据表记录时,需要保证数据一致性。
1.带约束条件的update操作
场景举例:
预付款充值场景,假设用户创建一笔账单用于充值,在充值前,系统将账单状态status置位“待支付”,当系统在收到成功充值的通知后,会设置status为“成功支付”,并累计余额。但由于一些原因,系统可能会收到多条同样的充值成功消息。系统针对每条消息都设置状态,虽然不会对账单的status本身产生负面影响,但每次都成功处理后,必然会导致余额重复增加,这显然是系统不希望达到的预期(当然用户本身是乐意的,白赚了,^v^)。为此,系统需要保证即使在收到重复通知时,只成功设置一次账单的状态,由“待支付”迁为“成功支付”,从而保证只对余额增加一次。
解决方案:
一般情况下,我们会通过在业务层面先判断账单的status为“待支付”时,才update状态为“成功支付”,其他非“待支付”场景,业务直接返回错误,即:
if(billEntity.status != "待支付"){ return error;}else{ //调用update操作,修改status状态 //update t_bill set status = "成功支付" where bill_id = $id}
但在高并发场景下,如果两个操作同时判断出status状态都为”待支付”,则依然会执行多次成功的update操作。
为此,我们在数据库层面也增加保护措施,通过增加约束的方式来执行update操作。具体方案如下:
string sql = @"update t_bill set status = "成功支付" where bill_id=$id and status = "待支付"";if( context.Dosql(sql) <= 0 ){ return error;}
在数据库中,当第二次执行update操作时,由于status在数据库中的值已经为“成功支付”,所以第二次update操作影响的记录个数会等于0,导致更新失败,从而保证了业务层面不会继续执行后续的逻辑。
2.增量update操作
场景举例:
预付款充值场景,假设用户的余额初始为100元,现在通过两台设备同时充值50元,则在两笔充值都成功的情况下,用户的余额应该变为200元。假设采用不带约束的update方式进行余额修改,即如下的sql语句:
update t_balance set balance = $newBalance
在并发操作时,如果以如下的顺序并发执行:
- A查出初始余额为100元;
- B查出初始余额为100元;
- A改写余额为100+50元;
B改写余额为100+50元。
很显然,由于第二次update改写操作直接覆盖了第一次的操作,导致最终的余额不符合预期。
解决方案:
这里我们可以根据增量更新的方式,每次update操作,不是将最终计算的结果先在业务层计算得出后写入数据库,而是将计算的逻辑放在数据库层去执行。于是改写后的update语句变为:
update t_balance set balance = balance + 50
通过增量更新,即使在并发场景下,也能保证每次update使用的旧值都为数据库中的最新值。
- 数据库Update操作的一些技巧总结
- delphi中操作access 数据库 Insert,Update的一些情况
- 关于数据库操作的一些总结
- Python中常用的一些操作总结(未完待续)update @ 2017-1-6
- 数据库的一些操作
- 数据库的一些操作
- c#中sqlite数据库相关的一些操作总结
- MFC 的一些操作技巧
- Win7的一些操作技巧
- 一些JS的操作技巧
- 窗口操作的一些技巧
- 一些位操作的技巧
- Unity3D的一些操作技巧
- MAC的一些操作技巧
- delphi的一些操作技巧
- 数据库的一些总结
- ASSERT技巧的一些总结
- Dorado的一些技巧总结
- hdu2152 Fruit
- idea新建分支
- db2数据库常用sql脚本
- 好忙
- 异常杂谈
- 数据库Update操作的一些技巧总结
- 【转载】windows dos命令
- 通向架构师的道路(第六天)之漫谈基于数据库的权限系统的设计
- 【转载】window dos
- window下sh文件在linux转码
- JVM内存区域详解
- oracle 正确删除归档日志,并清除 V$ARCHIVED_LOG 数据
- 【转】java代码注释规范
- 只是体系总结