由於 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,更多精彩內容等你來。

相關文章
相關標籤/搜索