标签 update 下的文章

某计费系统出了bug 出现了一批异常扣费记录,影响部分用户的余额。
需要找出异常的扣费记录不难,但不同用户的异常金额是不一样的。
因此无法简单用 'update set blance += patch_value ' 的方式划一校正。

方案一:研究SQL语法有没有办法 UPDATE 嵌套子查询,使每个用户发的 更新值不一样,发现这样写sql语句的逻辑繁琐语义风险高,抛弃!

方案二:用python或php脚本,先把异常扣费记录查出并根据用户统计,然后再逐个用户执行update。虽然可行,但补丁脚本怕被重复执行且执行后无事务可查不可逆,在业务层面并不理想,属于粗暴操作,也没有采用。

方案三:最终方案。计费记录表新增了一个对DELETE事件的触发器(trigger),当删除记录时将扣费的金额归还到用户的余额。这样做的好处是修正的余额由mysql内部逻辑实现。而且将来其他情况下需要对异常记录撤销也能满足余额自动返还。不用人为用写程序干预。

实现步骤

0.首先备份原数据

此步骤非必须,只是作为保险在进行操作前对相关数据进行备份,万一出现严重错误仍可把备份表还原。

#复制表结构
CREATE TABLE `paylog_bak` LIKE `paylog`; 

#复制数据
INSERT INTO `paylog_bal` (SELECT * FROM `paylog`);

1. 创建 trigger

CREATE TRIGGER `refund` 
AFTER DELETE ON `paylog`FOR EACH ROW 
    UPDATE `customer` 
    SET `balance` = `balance` + OLD.`amount` 
    WHERE `id` = OLD.`cid`

sql解读:
创建一个名为 refund (退款) 的触发器,当 paylog 发生 删除事件时
将删除行的支付金额(amount),增加到对应的客户表(customer)的余额(balance)

2. 删除异常的记录

此处sql略,根据异常数据的特征 DELETE FROM paylog WHERE .... 就行。执行后检查受影响的用户余额都有变化。

需求完美实现