iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 12
1
自我挑戰組

Let's Eat GO ! 實務開發雜談by Golang系列 第 12

Day12 .[正確資料篇] 不要用time.time型態的資料insert到MySql Datetime欄位

這篇分享的內容,比較像是遇到bug,使用mysql DB,程式寫資料進入再撈出所遇到的問題。

mysql DB 在欄位設計要記錄時間相關的欄位,我們便設定為Datetime格式。

而Golang我們使用了gorm的套件,

要傳入到insert的參數,在golang裡面是使用time.Time,在gorm log 和phpmyadmin觀察寫入的資料看起來是沒有問題的,譬如: "2019-09-06 14:01:02",大概長這子。

可是程式上線時開始遇到問題了,我們指定where條件撈出剛剛寫入的資料,其中包含了那個時間欄位,有時候怎麼撈都撈不出來。

見鬼了在phpmyadmin裡面看到"2019-09-06 14:01:02"是這個時間點沒錯,query的條件也是"2019-09-06 14:01:02"沒錯,那為什麼有時候會撈出不來?

查了各方面的狀況,最後從binlog的insert語法終見端倪,實際上寫進到DB的資料會像是"2019-09-06 14:01:02.234334",後面接了一串毫秒後的時間。

但是gorm的log和phpmyadmin卻看不到『秒』後面,而且query條件只到秒鐘,並不是每次都撈不出來,撈不出來反倒是少數。

所以後來要寫入DB的時間資料,到最終都會轉換成string,再寫進去,就樣就不會再出現這種莫名其妙被坑的情形。

延伸議題

可能有人會想問,為什麼要把剛剛insert的資料的資料,馬上再撈出來使用呢?

那是因為我們業務處理上,需要每筆寫入資料auto increament產生的流水號。

一筆一筆insert,的確能在當下回傳就拿到流水號,但是考慮到效能方面,這個作法實在太差,每次程式單元round一次可能就要寫入好幾萬筆insert,不做bulk insert實在是不好說得過去,而bulk insert怎麼去拿到每一筆的流水號?這我就不清楚。

於是需要額外一次的select,根據多個where條件,尤其是時間,來確認剛剛寫入的資料是哪些,再撈出後用程式抓取每筆的流水號做資料處理。

原本每次要好幾萬條的DB連線,有幾個insert就需要幾條連線,改用這個做法,只需要一次insert query和一次select query共兩條就解決了。 (可能要注意一下max preparement的數量)

如果有其他做法,歡迎留言告訴我~


上一篇
Day11 .[正確資料篇] graceful shutdown & restart
下一篇
Day13 .[心得與討論篇] 使用goroutine,如家常便飯
系列文
Let's Eat GO ! 實務開發雜談by Golang30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言