由于 Django ORM update,我今天差点「从删库到跑路」

通过周末两天回血,今天早早来到公司,准备把上周遗留的 BUG 修了,而后再多写几个 BUG。python

还没等我把双肩包放好,就看见群里有同事反馈,有一个表的数据没了。git

我一看,可不是,原来有几千条,如今就剩十几条了。github

大脑迅速转了几圈,相关代码我还真改过,但已是上上周的事了,初步断定,应该是跟我不要紧。可是,身为一名乐于助人的红领巾,我仍是要帮忙排查一下的。数据库

事情大概是这样:微信

咱们有一个定时程序,从数据源拉取数据,而后入到一个表里,没有则建立,有则更新。spa

还有一个定时程序,根据表的 update_time 字段来删除过时数据,过时时间是 7 天。code

快速浏览了一下代码,感受没有什么问题,同事也都表示,最近没动过相关代码。cdn

初步判断,多是数据源出问题了。blog

而后手动执行了一下拉取程序,数据源没有问题。get

那就奇怪了,难道真是我上上周改的代码出问题了?

心虚使个人后背微微冒汗,怀着忐忑的心情把以前的代码仔细看了一遍。看完后,我眼前浮现出三个字:没问题。

又叫来两个同事一块儿来帮我 review 一下,三我的对着电脑屏幕,望眼欲穿,频频发出感叹:这没问题啊!

其中一个同事看我用的 update() 方法,说:“是否是数据没变化,update() 就不更新了呢?”

我和另外一个同事同声反驳:“不会啊,怎么可能。”

我还补充道:“别这样,要对咱们学的知识有自信。”

不过,也实在看不出到底哪里有问题,死马当活马医吧。

我又跑了一遍程序,没想到打脸来的如此之快,update_time 字段还真的没更新。

因而,我改了一点程序,确保入库数据和数据库中的数据是不一样的,又跑了一遍。

发现我改的字段更新了,可是惟独 update_time 字段没更新。

而后我把 update() 方法改为 update_or_create() 方法又跑了一遍,由于我上次把 update_or_create() 改为了 update(), update_time 字段更新了。

纳尼?这究竟是为啥啊?懵了~

赶忙找谷歌大哥帮帮忙。

通常咱们定义 model 中的时间字段是这样的:

create_time = models.DateTimeField(auto_now_add=True, verbose_name="建立时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
复制代码

create_time 在第一次新增数据时建立,以后便再也不改变,update_time 会在每次数据更新时更新。

但,update_time 并不是每次都更新,好比使用上文提到的 update_or_create() 方法会更新,save() 方法也会更新。由于这两个方法都是走的 Django ORM。

而更适用于批量操做的 update() 方法则是直接执行数据库 SQL,不走 Django ORM,因此 update_time 也就得不到更新。那要想更新怎么办呢?手动给 update_time 赋值。

这也太坑了,程序欢天喜地执行了一周都没有问题,没想到隐藏了这么大的一个 BUG,真是学到了。

最后,感谢公司 DBA 大佬帮忙恢复数据,不论缘由,过去 7 天,想恢复到哪天的几点就恢复到哪天几点,体验简直不要太好,我想删库跑路都不行了。

技术博客:

github.com/yongxinz/te…

同时,也欢迎关注个人微信公众号 AlwaysBeta,更多精彩内容等你来。

相关文章
相关标签/搜索