分类 coding 下的文章

某计费系统出了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 .... 就行。执行后检查受影响的用户余额都有变化。

需求完美实现

此问题常出现在 MySQL 5.7.x 及以后版本(lnmp安装后的默认配置),解决方法备忘如下:

第一步,查看当前 mysql 的变量,运行

SELECT @@GLOBAL.sql_mode;

当中应包含 ONLY_FULL_GROUP_BY

第二部,运行以下这行声明变量(把上一段显示出来的照搬,去掉 ONLY_FULL_GROUP_BY)

例如(应根据第一步实际内容调整)

set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

然后再次查看sql_mode 如果目标参数已经不存在,尝试执行包含 group by 的sql,问题应该已经解决。

参考日志:
https://blog.csdn.net/qq_28867949/article/details/76850378

换了一台机器继续写处理doc文档的python,调试的时候才发现缺少 python_docx。

pip3 install python_docx

爆了一堆错,才发现之前编译安装python3 也没有装 setuptools 和 pip3 (不记得为什么和当时是怎么装的了)

pip装完之后发现直接安装还是报错。饶了点弯路,以下备忘怎样手动安装。

到这个地方下载需要的库的手动安装文件(.whl)

http://www.lfd.uci.edu/~gohlke/pythonlibs

搜索到 python_docx‑0.8.10‑py2.py3‑none‑any.whl 下载到本地

运行

pip install your/path/of/python_docx‑0.8.10‑py2.py3‑none‑any.whl

依赖lxml自动下载也失败,继续回上面的链接找 lxml 同样安装
版本众多,留意刚才安装python_docx时显示的相应版本

D:\>pip install d:\Download\python_docx-0.8.10-py2.py3-none-any.whl
Processing d:\download\python_docx-0.8.10-py2.py3-none-any.whl
Collecting lxml>=2.3.2 (from python-docx==0.8.10)
  Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='pypi.org', port=443): Read timed out. (read timeout=15)",)': /simple/lxml/
  Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out. (read timeout=15)",)': /packages/0c/94/68a055d7ea8801aa6f2a1159e1bb257afe2afb5f3f026e5b0b7e15cf28b4/lxml-4.4.2-cp35-cp35m-win_amd64.whl

找对应的版本(python3.5.x win 64位) 下载 lxml-4.4.2-cp35-cp35m-win_amd64.whl

再次顺序安装,搞定

pip install your/path/of/lxml-4.4.2-cp35-cp35m-win_amd64.whl
pip install your/path/of/python_docx‑0.8.10‑py2.py3‑none‑any.whl

再运行,正确调用 python_docx了。

实现这种效果,首次打开某个网页的时候要求输入账号密码

QQ截图20191010024834.png

如果不输入或输入错误,会提示

Unauthorized

This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.

我知道这种授权交互这并不优雅毫无设计可言,但应用于部署在公网的内部系统缺不失为一个简陋但有效的一道安全屏障。
以下是nginx和apache的实现流程概要(centos下为例):


- 阅读剩余部分 -