awesome-stored-procedure 羞涩发布!

  • 2019 年 10 月 27 日
  • 笔记

前段时间因为线下分析库上的存储过程SP无规范的泛滥,导致ETL和BI报表经常出现各种死锁阻塞问题。遂决定动手整个简单的SP编码规范,其实主要目的就是记录SP的运行日志和状态。

存储过程在很多“互联网新生代”程序员的观念里可能已经是上古物件了吧?现而今大部分的互联网系统实现都不太可能采用存储过程的实现方式,因为它对数据库造成的负担、难于调试、移植性差,以及在分布式、高并发场景下的天然劣势,都阻碍了它的使用。所以阿里巴巴Java编程规范里明确规定“禁止使用存储过程”也就不足为奇了。

但是很多公司的线下关系型分析库上,SP仍旧是相当常用的一种技术手段。SP泛滥后主要容易出现以下几点病症:

1. 基于SP创建的Event运行频率和运行时长设置的盲目且随意。这会导致:

  • SP自身本次还没运行完,下一个自己就启动了,结果自己把自己锁死;
  • 不同SP之间有依赖顺序,一旦前置SP出现超时,后续的SP执行只能是错误的或者锁死的状态;

2. SP的执行过程是黑盒、不可见的。准确的说就是SP在运行过程中没有足够的日志线索,很多时候只知道卡主了,但不知道卡在那里。

3. SP没有异常处理。SP运行过程中发生错误,若没有捕获处理,导致最终运行失败,那么这个SP在整个依赖链路的越前端,恢复成本将越高昂。

上述三个问题最终都可以靠一张日志表来解决,另外为了实现序号自增,又多建了一张序号表,总共2张表。

SP日志工具的代码我已经上传到了Github上,方便自己和大家翻阅。又因为本人特别喜欢Github上的Awesome系列,顺道碰个瓷,这个代码库命名为了

awesome-stored-procedure

https://github.com/NicholasQu/awesome-stored-procedure

目前都是基于MYSQL编写的,其他数据库的有空再考虑完善一下吧。接下来简单介绍下这几个Function /Procedure。

FUNCTION getSeqNo

/**********************************************

* 使用示例

**********************************************/

select getSeqNo('mall'), getSeqNo('pay');

功能:根据序号类别,获取全局自增序号。

不同类别的交叉运行会导致序号跳空,该函数不保同一类别内序号的连续性。

PROCEDURE logSp*

/**********************************************

* 使用示例

**********************************************/

call logSpStart('sp1','testing sp1',100,@sp_exec_no);

call logSpStartAndCheck('sp1','testing sp1',100,'sp2', date_add(now(), interval -1 minute), now(), @sp_exec_no);

call logSpEnd('sp1','end sp1', @sp_exec_no);

SP启动和先决条件检查

用于记录SP启动时间和状态,并检查可以继续运行的条件是否满足:

1. 自身的运行频度较高,之前自身是否还未运行完成。该情况调用logSpStart即可;

2. 依赖其他的SP运行完成,自身方能启动。该情况需调用logSpStartAndCheck;

SP调试信息打印

用于打印Info级别的调试日志, 调用logSpInfo;

SP结束日志打印 logSpEnd

用于表示该SP已运行完成。注意这里只标识SP的完成,并不一定成功,整个SP中间过程可能发生了异常,但是继续运行完毕了。

SP异常处理

对异常进行处理。有两种方式:

1. 若该异常无关痛痒,可以继续后续逻辑的话,使用logSpErrAndContinue;

2. 若该异常直接可以导致SP终止,调用logSpErrAndEnd;

标准SP写法

参照 p_sp_demo.MYSQL.SP.sql

https://github.com/NicholasQu/awesome-stored-procedure/blob/master/recordSpLogs/p_sp_demo.MYSQL.SP.sql


传送门再贴一次

https://github.com/NicholasQu/awesome-stored-procedure