解决一个程序问题需要多少步——确定我们没有在摸鱼

3 天前,运行的社区系统报告,很多老的历史照片都无法作为附件加载 —— 小鲨鱼,快来解决问题。

很多人都问题,为什么程序员每天不是在调 Bug 就是在调 Bug 的路上。

其实呀,计算机是一个逻辑性非常强的东西,每一步都应该是原因的,所以我们要通过逻辑性找到不同的原因。

这个和把大象关进笼子里有几步差不多。

调试的方法其实就是针对问题去找到原因,为什么会出现这个问题。

对 Web 系统来说,无非就是程序和数据,首先需要确定数据丢了没有,如果数据丢了,怎么调试都没有用,因此先恢复数据,保障系统运行永远是第一位的。

Step 1 有没有快速的解决方案

为什么会出现这个问题,不是好好的吗?原来是因为更换了域名,同时更换了云存储的存储路径。

现在问题就是主题中的内容都没有丢,但是当主题重新生成 HTML 后,只要主题中有附件的部分,全部都没有正确生成 HTML。

快点检查存储在云端的附件有没有被删掉。找到一个老的主题已经生成的 HTML,然后检查丢失的图片对比的服务器地址。

云存储的附件都还在,没有被丢掉,如果直接把绝对 URL 拷贝过来,问题就解决了。

赶紧的,有备份吗?

有备份,赶快恢复一次。

Step 2 数据恢复

恢复备份后无法解决问题。

备份恢复了,问题依旧。怎么办?

有多少主题被影响到?

往前面找 3 个月,1 个月,2 个星期的随机帖子,貌似各种情况都有,但是大量丢的都在 几个星期之前的,几乎都无法显示。

那应该是在生成 HTML 的短 Hash 代码转码回去的时候出现问题了。

这个数量已经非常大了,没有办法通过手工恢复的方式完成了。

这里有个判断,如果只影响到几个主题,通常我们都可以手工恢复的,如果影响的主题超过几十个,这个时候是没有办法手工恢复,只能找到原因让程序去做了。

Step 3 调试存储桶路径

因为我们知道存储桶路径换了,是不是因为存储桶的名字问题呢?

把服务器上存储桶的名字重新改回来,问题依旧。

现在这个和存储桶的路径应该没有太大的关系。

Step 4 调试 Hash 算法

是不是因为在 Base 62 Hash 算法的时候因为 SHA1 的不同而导致了算法没有被正常解码?

读了下程序,貌似问题也不在这里。

这个 Base62 算法,程序中没有加摘要扰乱计算。

Step 5 查询数据库的数据

现在我们得从数据库查看了,因为没有办法确定到底是程序还是数据的问题。

貌似在备份前 3 天的数据是好的,我们应该要把数据库的数据恢复下看看。

服务器现在在运行的,好在新加的主题没有问题,那就让服务器运行着吧。

我们把服务器上的数据 Dump 下来,导入到我们本地的 PGSQL 数据库中吧。

这个导入过程可能要一天也可能是几个小时,因为导入数据比较容易出错。

Step 6 如何进入服务器 Docker 容器内查询

数据本地拿到了,Hash 前的和 Hash 后的数据都在呀,那问题在哪呢?

到 Docker 容器内去查询下现有的服务器数据吧。

这个时候,你就可能需要时间去了解下如何进入 Docker,如何在 Docker 连接数据库后运行 SQL。

因为这个库是在容器内的,你是没有办法通过其他数据库工具直接连接到数据库上运行 SQL 的,通常生成服务器也不允许你这么做。

查询的结果,发现是本地有的记录,服务器上没有。

大概率知道数据库映射出了问题。

Step 7 把本地的备份数据恢复 1 条

把本地备份的 1 条数据恢复到服务器上,然后刷下效果,看是不是就是因为数据丢了?

太棒了,恢复的这条数据被显示出来了,主题正常了。

原来就是丢数据了,备份不应该是备份全部的吗?看来应该是恢复哪里或者某个表出问题了。

Step 8 获得具体有多少数据被影响

因为我们知道那个表现在有问题了, Select Count(*) 呗。

发现一共了 4000 多条记录被影响。

赶紧把本地的这些记录组织成 SQL 到服务器上运行吧,都是 Insert 应该问题大。哪怕是重复数据,因为有 Key,重复数据会被忽略掉。

导入后问题解决了。

Step 9 解决问题后 2 天同样的问题又出现了

先查 Count,后来发现 Count 数据被删掉了 2000 多。

这肯定是有自动运行进程对数据进行清理了。

上网考古下,发现貌似有一个无用附件清理进程会对程序认为无用的附件进行清理。

先不管了,把这 2000 多条数据恢复再说。

Step 10 关闭清理进程

先关闭清理进程,然后看为什么这个程序会把我们实际是需要的数据给清理掉?

读代码,在清理之前,程序会判断那些数据是需要清理的,这里有一个 Join 的 SQL 查询。

这里 Join 了另外一个表。

Step 11 对比 JOIN 表数据量

马上对比另外表的数据量。

这里了明显又丢了好几千条记录。

原来在主题和附件的关系映射表中的数据丢了部分,导致整个附件表的有用数据被当做无效数据清理掉了。

Step 12 数据恢复

把 JOIN 的映射表数据进行恢复。

然后等待重构运行结果,保持清理进程开启,2 天后查看结果。

同时增加服务器备份数量,从保留 30 天的备份,到现在增加到保留 300 天。

Step 13 问题总结和记录

把整个过程总结下来,花个 10 多分钟记录下问题。

上面是针对一个问题进行调试的小过程,如果你对系统比较熟悉的话,很快就会定位到映射部分。如果对系统不熟悉的话,上面的步骤就是一个几乎完整的 Debug 流程。

在上面的流程中到处都是坑,这就是为什么有些人看起来只需要几个小时或者几分钟就解决问题了,你却用了几天的时候,甚至几天都没有进展。

相信我,不是因为你不够优秀,仅仅是因为你对已有的这套系统的设计,数据,逻辑不熟悉而已,这没什么大不了的,时间问题。