原本预期1小时的发布,为何最终发布加校验实际花费时间5小时

这是一个简单的数据生产导入的故事,原本故事情节应该是这样的:数据整理-->测试验证-->生产发布-->生产验证,然后就是各回各家,所以这本来应该是一个平淡的故事,然而实际却变成了如下情节:数据整理-->测试验证-->生产发布-->生产验证-->校验失败(预期数据未导入)-->问题排查-->解决问题-->生产发布-->生产验证-->校验问题(大部分数据是正确的,少部分数据不正确)-->问题排查(当时未能排查出原因,但能判断出异常与生产原有的几条异常数据有关)-->异常数据删除sql编写-->测试校验-->生产发布-->生产校验-->重新导入删除部分数据(异常数据这次直接排除,没包括在导入范围)-->部分异常数据请示领导修正-->修正Sql准备-->测试校验-->生产发布-->修正数据对应数据导入-->生产校验!

你以为到这里就结束了?NO NO NO,故事怎么可能就这么结束,因为这批数据导入有对应的其它业务,还需要执行该部分业务,最终确认后才能各回各家,结果发现,坑爹的数据库数据是修正了,但因为程序采用了Redis,异常数据还在Redis中,所以还要在Redis中删除该部分异常数据,还好程序部分对此有处理,直接删除没导致程序功能异常,至此本次发布才算结束,但此时也已经是凌晨0点了,这真是一个悲剧的故事……

首先需要介绍下本次导入的猪脚,一个预先写好,且已经发布至生产的存储过程,另外该猪脚所在场景是MySql,其大致代码精简后如下

 1 DROP PROCEDURE IF EXISTS `usp_SadEvent`;
 2 DELIMITER $$
 3 CREATE PROCEDURE `usp_SadEvent`
 4 (
 5 IN identityNo VARCHAR(20),
 6 IN uName VARCHAR(15),
 7 IN cAmount LONG
 8 )
 9 label_at_start:
10 BEGIN
11
12 SELECT @uid := id FROM `user`
13 WHERE identity_no=identityNo AND NAME=uName;
14
15 IF @uid IS NULL THEN
16     select identityNo,uName,0 ret;
17   LEAVE label_at_start;
18 END IF;
19    update account set balance=balance+cAmount where uid=@uid;
20     select identityNo,uName,1 ret;
21 END label_at_start$$
22 DELIMITER ;

首先就是what the fuck的执行失败问题,调用该存储过程结果居然都是返回ret=0失败!!

还好当初写存储过程时,考虑到了结果查询,比较容易就发现为什么返回的uName是乱码?碰上这种问题,直觉就是数据库编码有问题,一查果然如此

问题查出来了,怎么修正呢,正常剧情当然是改数据库默认编码为utf8了,但改编码后Mysql必须要重启,生产环境是你想重启就能重启的吗?好吧,还好mysql存储过程支持指定编码,修改存储过程,在uName部分指定编码集是utf8(补充虽然数据库默认字符集是latin1,但实际里面的表在创建时都默认指定utf8了,所以导致一直没发现生产环境居然有默认编码集问题)

IN uName VARCHAR(15) character set utf8,

改完后执行批量调用存储过程的sql,大致如下

call usp_SadEvent(‘123131231313123132‘,‘张三‘,3000);#数据库有
call usp_SadEvent(‘123454566778899999‘,‘李四‘,5000);#数据库无李四,或数据库里叫李斯

这里特别标明第一条数据库里是有对应数据,第二条在数据库中是查不到用户数据的,执行结果居然发现第二条“李四”的金额,被加到了“张三”身上,这又是什么鬼!

其实问题就出在mysql的默认声明参数上,只要在上面的调用语句下面再加一句

call usp_SadEvent(‘123131231313123132‘,‘张三‘,3000);#数据库有
call usp_SadEvent(‘123454566778899999‘,‘李四‘,5000);#数据库无
select @uid;

执行结果很明显的就告诉你@uid是有值的,而且值为张三的uid,好吧,没想到Mysql中

SELECT @uid := id 

这种隐式声明参数的方式居然会在整个对话期间内都有效,所以还是老老实实改成如下显式声明才能测试正确

declare u_id long;
select `id` into u_id FROM `user`

最终完整修改后的存储过程应该如下

DROP PROCEDURE IF EXISTS `usp_SadEvent`;
DELIMITER $$
CREATE PROCEDURE `usp_SadEvent`
(
IN identityNo VARCHAR(20),
IN uName VARCHAR(15) character set utf8,
IN cAmount LONG
)
label_at_start:
BEGIN
declare u_id long;
select `id` into u_id FROM `user`
WHERE identity_no=identityNo AND NAME=uName;

IF u_id IS NULL THEN
    select identityNo,uName,0 ret;
  LEAVE label_at_start;
END IF;
   update account set balance=balance+cAmount where uid=u_id;
    select identityNo,uName,1 ret;
END label_at_start$$
DELIMITER ;

哎,事后描述问题似乎很简单,实际排查这些问题还是挺坑的,哎……

时间: 2024-11-08 21:20:24

原本预期1小时的发布,为何最终发布加校验实际花费时间5小时的相关文章

疯狂猜成语-----最终发布版的总结

疯狂猜成语 小组人员:杨霏,袁雪,胡潇丹,郭林林,尹亚男,赵静娜 最终发布版界面: 总结: 在为期一个学期的努力,我们小组最终完成了"疯狂猜成语"的软件设计及发布.在此过程中通过对用户进行交流,在最大程度上满足用户的需求.在内部测试版发布的时候,发现了好多不好的地方和有待改善的细节,经过对我们软件的升级和修复,我们在最后发布了如上图的软件.在用户中进行运行和推广,用户对我们做的东西非常感兴趣,得到了好多好评,同时也对我们的软件提出了不少意见. 疯狂猜成语-----最终发布版的总结,布布

互联网产品发布之灰度发布

1. 为什么要灰度发布 互联网服务变动频繁,发布周期短.速度与质量总是难以双全. 灰度发布能降低发布风险,减少影响范围. 降低对测试的依赖,减少线下自测的数据构造成本. 方便集中监控日志,全量发布由于各层负载均衡的作用,很难跟踪一条完整的调用链路. 可以灰度测试帐号,测试账户通过之后再灰度真实用户帐号,进一步降低发布的风险和影响. 方便回滚. 不能靠灰度发布解决的问题 需要强调的是:上文所说的“可以容忍的影响”必须是可恢复的,比如API无法调用一段时间,但是修复之后,就可以成功调用.而永久性地丢

.net 获取网络时间(北京时间)24小时制

/// <summary> /// 更新系统时间 /// </summary> public class UpdateTime { //设置系统时间的API函数 [DllImport("kernel32.dll")] private static extern bool SetLocalTime(ref SYSTEMTIME time); [StructLayout(LayoutKind.Sequential)] private struct SYSTEMTIM

【原创】我所理解的自动更新-APP发布与后台发布

发布后台 创建渠道:添加新的渠道,设置渠道名称,自动生成渠道id.    查看渠道:查看渠道基本信息,渠道app版本号,资源版本号,是否开启更新.    创建/更新APP:选择打包ios,android版本,设置渠道所属,设置版本日志,发送消息到APP Publish并等待反馈.    创建/更新资源:设置渠道所属,设置版本日志,发送消息到ResPackageTool并等待反馈. APP打包发布 从VersionServer里获取相应渠道的代码,保存到目录[channel-渠道号-版本号]. 

IIS发布网站出现“未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项。”的解决方法

未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序.              说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息.             异常详细信息: System.BadImageFormatException: 未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序.源错误: 执行当前 Web

WebForm发布提示:无法加载或找不到oracle.dataaccess文件

出错提示: 在32位错做系统的开发机上引用了第三方插件(oracle的dataaccess)完成的项目,将发布的程序拷贝到64位的服务器上进行发布时提示无法加载或找不到dataaccess文件. 错误原因: 因为是在32位的的服务器上开发,在添加引用文件时,添加的引用文件是在32位操作系统上使用的,而在64位系统中则会找64位的文件所以导致找不到或版本不对,从而导致报错. 解决方法: 1.在64位操作系统找到对应的引用文件(oracle的dataaccess),要是64位操作系统使用的文件,拷贝

主干发布和分支发布

一:主干发布 先说主干发布模式: 以SVN库为例,大致将库分为trunk, branch,tag三种,主线发布就是公司要发布某个产品的V1版本,之前大家都做会在SVN的trunk上做开发,等 trunk稳定了.开出一个分支B1,在B1分支上做V1版本的其它功能添加,bug修改等,并使用持续集成来验证B1的稳定性.直到V1版本达到要求, 可以对外发布,并且发布成功后,进行从branch到trunk的merge操作,此时trunk上的内容变成了V1版本的内容,而后trunk上的内容不再允许修改.然后

【微服务从入门到精通】:(一)微服务的蓝绿发布及灰度发布

蓝绿部署 基本上,蓝绿部署是一种以可预测的方式发布应用的技术,目的是减少发布过程中服务停止的时间. 简单来说,你需要准备两个相同的环境(基础架构),在蓝色环境运行当前生产环境中的应用,也就是旧版本应用,如图中 App1 version1 . App2 version1 . App3 version3 . 当你想要升级 App2 到 version2 ,在蓝色环境中进行操作,即部署新版本应用,并进行测试.如果测试没问题,就可以把负载均衡器/反向代理/路由指向蓝色环境了. 随后你需要监测新版本应用,

蓝绿部署、滚动部署、灰度发布、金丝雀发布

微服务部署:蓝绿部署.滚动部署.灰度发布.金丝雀发布 在项目迭代的过程中,不可避免需要"上线".上线对应着部署,或者重新部署:部署对应着修改:修改则意味着风险. 目前有很多用于部署的技术,有的简单,有的复杂:有的得停机,有的不需要停机即可完成部署.本文的目的就是将目前常用的布署方案做一个总结. 一.蓝绿布署 Blue/Green Deployment(蓝绿部署) 1.定义 蓝绿部署是不停老版本,部署新版本然后进行测试,确认OK,将流量切到新版本,然后老版本同时也升级到新版本. 1.特点