序列和時間戳的替代方案:按時間唯一排序記錄
Oracle 11gR2 Exadata
我需要唯一標識何時及時創建記錄。序列記憶體意味著我不能使用基於序列的 ID,而批量插入意味著在一個批次中插入的所有記錄都將具有相同的時間戳值(即使使用 TIMESTAMP(9))。類似於 Twitter 的since_id 概念。
到目前為止我想到的最好的選擇
- 創建用於每個唯一時間戳的附加序列
- 不批量插入記錄以強制每條記錄使用唯一的時間戳
- 不記憶體序列,儘管有一些討論認為這不會解決 Exadata 下的問題
這是我的要求:我有一個 API,它允許使用者提供一個序列作為標記並請求從那時起的所有記錄。例如,他們請求標記為 7 的 1000 條記錄,他們將從我的表中獲取 1000 條 ID 大於 1007 的記錄。例如,假設返回的 1000 條記錄中數字最大的 ID 是 2045,所以我們返回 2045 為標記 後來,客戶請求 1000 條記錄,標記為 2045,期望獲得下一批 1000 和新標記。
非常簡單的方法可以讓他們以適合他們的任何大小獲取所有記錄而不會失去任何記錄。但是,由於跨多個 Exadata 節點的序列記憶體,在客戶端請求標記為 1007 的 1000 條記錄時,可能尚未創建 ID 為 2020 的記錄。因此,當他們使用 2045 標記進行下一個請求時,他們將永遠錯過 2020 年的記錄。使用 ID 獲取關聯記錄的時間戳可以解決這個問題,但是我必須確保始終將記錄單獨插入表中以保證唯一的時間戳。
假設:
- 不是為批量/批量插入的單個記錄獲取單獨時間戳的方法
- 即使在序列上使用 NOCACHE,多個節點也可能導致記錄的插入是非時間順序的(例如,序列值為 180 的記錄可以使用大於序列值為 179 的記錄的 systimestamp 寫入)
希望我只是沒有找到正確的術語來搜尋現有答案。我覺得這是一個多年來應該通過一些模式來解決的問題。我認為Twitter已經解決了它……
我建議按時間戳排序。只要在同一事務中插入唯一具有相同時間戳的記錄,就可以使用基於序列的 ID 作為二級排序。
好吧,事實證明,在初始插入完成後,我需要使用同步過程為每條記錄分配一個 ID。
正如向我指出的那樣,我真正想要的是一個送出序列。不幸的是,即使時間戳也不會提供,因為它是在插入時生成的,而不是在送出時生成的。因此,在某些情況下,一組記錄 (A) 的時間戳可能在第二組記錄 (B) 之前,但組 B 實際上可以首先送出到數據庫。那我就沒有解決原來的問題。
最後,我們通過使用表鎖定(在“序列”表上)和跳過鎖定的過程使用了本質上是同步的家庭實現的序列。因此,我們不必通過單執行緒來減慢我們的插入過程,但我們保證了一個 ID,該 ID 保證在該 ID 送出到記錄時的送出順序中。