[DEBUG篇],一个开源项目的bug,如何深入源码修复...

136 阅读7分钟

记得上一篇我笔记,我记录了一个关于nodejs定时自动备份Mysql数据防止丢失的笔记,这个功能在我的便签需求池里面也一直放着,很久了都还没动过,又担心哪天服务器给攻击了,数据库给攻击了万一数据全丢了岂不完了,想了想后,提起Vscode就开始干,引入了个node的mysqldump模块,在install了个node-schedule模块,一个是mysql备份用的,一个用来开启一个定时任务,短短没几行代码功能就能搞定了,心里也总算踏实了一点 ....,

上一篇笔记 : juejin.cn/post/730235…

直到昨天,我把服务器备份的mysql数据包download了一份下来,导入到我本地数据库用来前端调试,导入完,我把项目跑起来看了下,结果变成这样了...

开始还以为是我前端的编码错了,看了下也是UTF-8阿,在仔细看了看我的其它数据是正常的,好像就有部分数据是乱码,打开浏览器调试器看了下请求数据,还真是数据出了问题,查了下还以为是我数据导入mysql的时候,忘记设置啥编码了或导入的时候数据解析出错; ,来回看了一遍好像也没有发现有别的需要设置的,把数据清掉重新导了好几次,发现还是一样,一时的给我差点整迷茫了

我本地的操作好像都没啥问题,就看了下我download下来的Sql备份数据包,果然备份的数据包里面的数据就是乱码的,所以导致我数据导入也是乱码,但是为什么只有部分是乱码,而其余的又都是正常的,如果是编码错了,大多数情况下应该是所有中文数据都会乱码才对阿,这就有点诡异了

排查了一圈,只少也确定了问题出在哪里,我把后端的代码跑起来,开始看我代码备份的逻辑,但是代码自动备份的逻辑就那么短短没几行,

主要还是依靠 mysqldump 这个包完成的,看了这个包的文档,有个 charset 的参数,还以为是这个参数没有设置的原因,加上这个参数试了一下好像也一样,官网文档上好像也没有其它需求配置的了,这就给我整糊涂了,

我看了下备份的数据包数据,好像发现了点问题,数据库里面其它的字段都没有乱码,只有有几个字段数据类型是json的里面的中文乱码了,这下好像明白了一点,我试着把json类型该成text类型试了一下,在执行备份导出,果然正常了,这是啥原因....

可能是 mysqldump 这个包里面有点不兼容 json 类型,如果用现成的方法解决,直接把数据库用到的json类型全改为text好像也有点不妥,如果是占用比较大的几个字段改为text还凑合,里面还有一些占用空间不大,用varchar的话又小了点,同样改成text就有点得不偿失了,而且为了一个小功能,让整个数据库做出妥协好像也有点不太合理

折腾了一圈,没法子了,就干脆在找找其它备份方案,百度查了一圈,GPT也问了一圈,给出基本上都还是差不多的同一个方方案,手动执行SQL备份命令,用网上的方案我本地调试,一直都调不通,也没报错,也没查出原因了,这里又费了我个来小时,也没搞定,而且还发现这个方案好像还有一点点小问题,就是导出的SQL数据包是压缩的,基本上也没法浏览,而一直没调通,干脆就算了,害,心累...

折腾了一圈,对比了一下发现还是原来的 mysqldump 这个包最好使

这个包的主要问题是json编译会乱码,可能作者自己也还没发现这个问题,其它都挺完美,使用也很简单方便,而且导出的SQL数据包是带有规范格式的,

毕竟也折腾到这里,而我系统的数据库自动备份功能也肯定是必须要的,不然我这写笔记都不太安心,只能着手试着看看能不能解决这个问题

我在npm网站上面找到了这个包,把上面的源码copy了一份下来,源码也不多,九百不到一千行代码左右

在我本地项目里面新建了一个js文件放进去,把原来引用这个包的路径改为了本地路径,用来调试源码

       

一放到本地调试,控制台出现了一堆的提示,果然真是json数据格式引发的问题

但是怎么解决呢? 还是一头雾水! ! !

我开始浏览copy下来的源码,从整个代码的逻辑入口,一路往下看,大致明白了一个基本的原理,里面的通过mysql2连接数据库,在手动把数据查出来,在写入文件的,我开始还以为是一些什么高端操作一键导出啥的

这下就好办了,毕竟mysql2这个包我平时用的也还比较多,我输出了一下,查询的数据,发现数据一查询出来就是乱码的

我记得我之前使用mysql2是不会有这个问题的,我自己单独新建了一个js文件在里面测试mysql2这个包,发现查询出来的数据也没问题啊,没有一个是乱码的

这样来看肯定是有些什么特殊配置,我看了下 mysqldump 里面用mysql2连接mysql传的参数,里面有个 typeCast 的参数,这是个啥东西,我给它注释了,保存热跟新运行后,发现决然没有乱码了????

给我激动的,赶紧百度查了一下,mysql2的配置参数,原来是一个格式转换,似乎明白了点啥,

我以为这样就可以了,我把本地编码正常的SQL数据包,在Navicat中进行导入,发现报了一堆错,原来把格式转换去掉后,里面有些数据需要用引号引起来的那个引号也没了,导致导入数据的时候mysql把这个值是转为了一个变量,一个不存在的变量

看来那个 typeCast 这个参数还是不能注释,加上的或又会json编码错误,延这 typeCast 这个参数的逻辑我看了下,这个参数传的是一个函数,而且还是一个闭包函数

我在这个函数里面用console输出了下里面 field 的数据,发现数据到这里的时候是还没有乱码的,但是一旦经过完这里有些数据就乱码了,这下问题就具体了,肯定就出在这这个函数的逻辑里面

看了看上下文的代码逻辑,如果字段是json的话,逻辑会走这里,让后就直接是把这个value返回了出去

就这么一小段, field 的里面的数据还是正常的,上传输出看过了,到这里我在console了一下 field.string() 这个东西,果然问题就出在这

我之前好像也没用户mysql2的string()这个方法,我在这个方法里面试着传了一个参数utf8,保存看了下导出的SQL数据包,居然......好了......

                                                   我这激动的心

                           神啊~ 快凌晨两点了, 终于可以去睡觉了

冷静, 冷静 ,本来还准备去这个包的github贡献点代码来着

结果作者搁这留了句话

                                  This project is no longer actively maintained

                                            (此项目不再处于主动维护状态)

也就算了