資料表欄位預設值是 sysdate or systimestamp,但當程式用時間區間卻抓不到

資料表欄位預設值是 sysdate or systimestamp,但當程式用時間區間卻抓不到

情境:資料庫裡跟日期有關的欄位,有建立預設值是 sysdate or systimestamp,但當程式用時間區間抓資料的時後,卻找不到?

例如,有一個資料表有「建立時間」的欄位,預設值是 sysdate。另外也有一個 service,每一秒會不斷的來 pulling 「建立時間」落在前一秒的資料。但卻不知怎的,有時後有些資料總是會沒被抓到。

可能原因

在新增資料時,那一整個 transaction 的處理時間過久,導致太慢才 commit。

在 oracle 裡面,一整個 transaction 是歸屬於特定一個 session 來動作的。如果這整個 transaction 還沒 commit,已異動的資料都還只有當前的 session 看得到,其它的 session 是都還看不到的。

所以假設一整個 transaction 的第一步就是新增資料(此時 default sysdate 就會先抓當前時間)。但是後面的動作做了「10」秒才做最後的 commit。

這時如果在第「10」秒 commit 前就有人開始來查資料,即使那個 default sysdate 欄位的時間符合條件也沒用。因為在它還沒 commit 前,別的 session 是看不到這筆資料的。

可能解法一

如果設計上是用 service 來 pulling 某個表資料並且又是用時間區間來更新資料的時後,可能試著把時間區間多往前抓一點,留點緩衝的時間。讓 transaction 做得比較慢的時後,也抓得到。

但缺點是多抓一堆沒用的資料,並且 trasaction 如果發生極端案例,很慢才 commit 的話。那也是解不了。

可能解法二

設計上如果也是要pulling 某個表資料並且又是用時間區間來更新資料的話,可以把有異動的資料鍵值或是主要的欄位值寫到另一個等待要被同步的表。

這個等待要被同步的表可以多加上一個「狀態」欄位。Service 只要來 pulling 「狀態」欄位是尚未處理過的,並且用紀錄到的鍵值或主要欄位來反查資料即可。