zoukankan      html  css  js  c++  java
  • 一种登记账后余额的处理方法

    支付系统的记账业务,需要登记每笔记账流水的账后余额。
    在大规模并发条件下,简单使用乐观锁或者悲观锁都回严重的锁定数据库,导致性能变慢,下面介绍优化前和优化后的两种处理思路。

    第一种方案,使用乐观锁
    实现过程:
    Step1:从账户中获取最近余额以及账户当前版本号,代码如下:
    Select version, balance from account where customer_no=?
    Step2:创建账户流水
    Insert into account_flow(version, amount, balance, customer_no) values(:version+1, amount, balance+amount, customer_no)
    Step3:更新账户余额
    Update account set version=version+1, balance = balance + amount where customer_no=:customer_no and version=:version
    在并发量小的时候,这样写基本没有问题,可以保证每笔交易的记账流水都是OK,然而,并发大的时候,会发现Step3中的红色部分的条件,完全Hold不住了,还没等待一笔交易完成,可能version已经变化了不止一次

    第二种方案,使用触发器
    实现过程:
    Step1:创建过程表
    Create table account_his(account_id, version, pre_version, balance, pre_balance, uid)
    字段分别是:账户ID、当前版本号、前一版本号、当前余额、前一版本余额、唯一ID(后面解释)
    Step2:创建针对account的触发器
    Create or replace trigger account_change_trigger before update on account for each row
    Begin
      insert into account_his values (:old.account_id,:new.version,:old.version,:new.balance, :old.balance,:new.uid)
    End
    Step3:修改记账过程
    1、生成uid=uuid
    2、更新账户余额:update account set uid=:uid,balance=balance+amount where account_id=xx
    3、登记记账流水:insert into account_flow values(account_id, amount, uid),注,此处暂时不登记余额
    4、使用定时器,从account_his中更新account_flow的余额:update account_flow set balance=account_his.balance where account_his.uid=account_flow.uid

    虽然触发器对数据库性能存在一定的损失,但这个好处还是明显的。

  • 相关阅读:
    Apache mod_rewrite
    vim 常用设置
    ssh 和 scp 命令访问非默认22端口。
    gulp常用插件
    gulp+Babel 搭建ES6环境
    ES6类与模块
    Autoprefixer处理CSS3属性前缀
    js模块方案
    ES6转码器babel的使用
    window.history.pushState与ajax实现无刷新更新页面url
  • 原文地址:https://www.cnblogs.com/hifong/p/8401397.html
Copyright © 2011-2022 走看看