数据库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

在并发操作时,如果以如下的顺序并发执行:

  1. A查出初始余额为100元;
  2. B查出初始余额为100元;
  3. A改写余额为100+50元;
  4. B改写余额为100+50元。

    很显然,由于第二次update改写操作直接覆盖了第一次的操作,导致最终的余额不符合预期。

解决方案:
这里我们可以根据增量更新的方式,每次update操作,不是将最终计算的结果先在业务层计算得出后写入数据库,而是将计算的逻辑放在数据库层去执行。于是改写后的update语句变为:

update t_balance set balance = balance + 50

通过增量更新,即使在并发场景下,也能保证每次update使用的旧值都为数据库中的最新值。

数据库Update操作的一些技巧总结相关推荐

  1. oracle update 数据库恢复,ORACLE update 操作内部原理

    对于oracle的update操作,在数据块中具体是如何出来,是直接更新原来值,还是通过插入新值修改指针的方法实现.下面通过证明: 模拟表插入数据 SQL> create table t_xif ...

  2. thinkphp mysql cache_thinkPHP5框架数据库连贯操作之cache()用法分析

    本文实例讲述了thinkPHP5框架数据库连贯操作之cache()用法.分享给大家供大家参考,具体如下: 介绍 TP5中自带的缓存系统,是File型缓存.也就是文件型缓存.存储地址是:根目录..unt ...

  3. datetime类型怎么输入_精心整理MySQL基本使用(数据库的操作、数据类型、MySQL的常用命令)...

    前言:瑞典 MySQL AB 公司开发,目前属于 Oracle 公司. MySQL是一种关联数据库管理系统 由于其体积小.速度快.总体拥有成本低.MySQL软件采用了双授权政策(本词条"授权 ...

  4. python操作sqlite数据库_Python操作Sqlite正确实现方法解析

    Python编程语言的优点非常多,它的编程特色主要体现在可扩充性方面.那么,在接下来的这篇文章中,我们将会为大家详细介绍一下有关Python操作Sqlite 的相关应用技巧,希望可以给大家带来些帮助. ...

  5. 使用动态代理实现用AOP对数据库进行操作

    使用动态代理实现用AOP对数据库进行操作 2008-03-14 11:04 作者:reverocean 来源:赛迪网 [摘要] 要实现对数据库的操作,离不开数据源(DataSource)或者连接(Co ...

  6. MySQL数据库update语句使用详解

    MySQL数据库update语句使用详解 本篇文章我们来讲讲如何对MySQL数据库进行更新操作,对数据库进行增删改查操作是我们必会的基础之一,会了这个增删改查我们可以在这基础上去编写更多的东西,废话不 ...

  7. vc6.0 点击鼠标获取mysql数据库所在行_VC6.0中对MySQL数据库的操作

    VC6.0中对MySQL数据库的操作 1.在mysql目录下找到名字为libmySQL.dll和libmySQL.lib 的文件拷贝到当前工程目录下,并在"工程->设置->连接& ...

  8. 【数据库】MySQL奇淫技巧(基础篇)

    前言:由于mysql有很多很多"特殊的用法",在此成其为奇淫技巧,很多用法很冷门,虽然由常用命令拼起来的,但是不是十分常用.对待一些特殊需求查资料都不太描述,这是个很尬的问题,所以 ...

  9. 从C#到Objective-C,循序渐进学习苹果开发(7)--使用FMDB对Sqlite数据库进行操作

    本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本篇主要开始介绍基于XCod ...

  10. QTP中对数据库的操作(查询,更新和删除等)

    标题为QTP对数据库的操作,其实应该改为QTP/VBS对数据库的操作.因为QTP中就是通过vbs完成数据库操作的.以access为例. 通过ADO对数据库访问的步骤如下: a.创建一个到数据库的 AD ...

最新文章

  1. CRF(条件随机场)与Viterbi(维特比)算法原理详解
  2. 【点云重采样Resampling】Python-pcl 基于多项式平滑点云及法线估计的曲面重建
  3. android 绘图之Canvas,Paint类
  4. 第5章 案例研究: QuickCheck
  5. laravel在wamp中输入地址后总是无法访问
  6. jenkins配置git出现ERROR: Timeout after 10 minutes 同时命令行出现:Enter passphrase for key 的提示
  7. Sentinel授权规则及规则持久化
  8. 昨天看了华星巨幕《海神号》
  9. 被劝退的准中年人日记——劝退后第一天
  10. win11虚拟内存怎么修改 Windows11修改虚拟内存的步骤方法
  11. LSH︱python实现局部敏感随机投影森林——LSHForest/sklearn(一)
  12. 数据结构与算法 - 图论
  13. python 提取代码中的所有汉字
  14. 计算机应用技术辅助设计方向课程,AutoCAD计算机辅助设计课程标准.doc
  15. python 山脊图_《图像处理实例》 之 寻找山脊线
  16. AutoLISP将图形中文字写入外部文件
  17. server 服务器文档,服务器文档,server document,音标,读音,翻译,英文例句,英语词典...
  18. 类似安卓的点9图片,气泡图片调成自己需要的
  19. springboot多数据源如何配置驼峰映射或配置文件不起作用的问题
  20. osgi 学习系列(一)搭建osgi platform环境

热门文章

  1. ZDM按横断面水位线河道开挖
  2. 解决OneNote for Windows 10 不能打开onedrive上已有笔记本问题
  3. I/O多路复用select服务器
  4. S32K的flash组件使用(操作FLASH)
  5. [Unity][AssetBundle]本地其他项目AB包加载AB打包文件文件路径
  6. 如何给老年唱戏机下载有声小说
  7. Java中的双重检查(Double-Check)详解
  8. 〖强暴贴〗号称全国最大开发者网络的CSDN多次出现低级错误 验证码形同虚设 开发人员竟是MVP
  9. Flex 加载Base64编码的二进制字符串图片
  10. android listener使用实例,如何使用lambda表达式/缩短onclicklisteners android studio(示例代码)...