← 所有文章

FIELD NOTES / 資料記錄與報表

事件資料庫去重與遲到事件以事件ID和來源時間重建順序

資料記錄與報表作者:站長預估 5 分鐘閱讀

以穩定事件身分去重,分開衝突、遲到與排序,重建可信的事件及報表區間。

本文目錄

先分清重送與另一個真實事件

設備斷線後一次補送多筆事件,資料庫可能收到重複、遲到與順序顛倒的資料。這三件事分開處理:去重辨認同一事件,時間規則決定歸屬,排序則重建可解釋的先後。只按收件順序排,再刪掉數值一樣的列,容易同時漏掉真事件與保留假重複。

事件ID應在事件形成時決定,重送保持不變。若每次傳送都重新產生ID,接收端只會看到多筆不同事件,無法用ID辨認重送。反過來,兩件產品即使測得相同數值,也應有不同事件身分,不以內容相同直接刪除。

準備一份事件明細,至少包含來源識別、事件ID、來源時間、收件時間、事件種類、資料內容與品質。若來源只能提供局部序號,還要定義序號的唯一範圍,例如設備加啟動世代加序號,避免重啟後從一又開始而撞到舊事件。

本文討論事件模型與重建步驟,不假設每台PLC天然提供全球唯一ID。PostgreSQL的唯一性約束只是資料庫端工具,事件身分仍須由系統設計定義;其他資料庫的空值與唯一性行為要另外查證。

用四筆到達資料看清三種問題

教學資料按接收先後為:A站事件102,來源十時零二秒;事件101,來源十時零一秒;事件102的重送;事件103,來源十時零三秒。這四筆接收紀錄只代表三個不同事件,去重後應保留101、102、103各一筆有效事件。

三筆按來源時間可排成101、102、103,但接收順序原本是102在101前。不要改掉來源時間去配合接收順序,否則原製程的先後就被抹平。原始接收紀錄仍可另留,用於診斷重送次數及傳輸延遲。

若同一ID第二次帶來不同內容,例如第一次測值253、第二次999,就不是可以靜默忽略的普通重送。標成身分衝突並保存兩份內容及來源,依規則處理,不以最後收到者自動覆蓋已發布的結果。

若來源時間相同,先查時間精度及來源序號的語意。可以按來源序號作同一來源的次序依據,或增加穩定的顯示排序鍵,但要說明穩定排列不等於已證明真實先後。不同設備的序號通常不能直接互相比較。

完成這組例子,應能同時回答收到幾筆、不同事件幾筆、重送幾筆與衝突幾筆。只留最後總數三,會失去診斷傳輸行為的重要資訊。

去重規則要能跨重啟與併發

內容比較需先約定哪些欄位代表事件本體。重送時收件時間必然不同,不應因此判內容衝突;數值、單位、事件種類及原始來源時間等關鍵欄位則按資料契約核對。若使用摘要指紋,保存計算欄位與序列化規則。

唯一鍵的組成依事件範圍決定。假設本例每台設備在每次啟動世代內的序號唯一,則設備、世代與序號一起構成身分;世代不能在每次接收端重啟時任意改掉,否則同一補送資料會被認成新事件。

若使用PostgreSQL 18,普通唯一約束對空值的預設處理可能允許多個含空值的組合。必填識別欄位應明確禁止空值或採符合設計的約束,不以為加了唯一鍵就自動驗證每個ID都完整。本文不提供未經實際結構確認的建表腳本。

兩個接收工作可能同時查到事件不存在,再同時寫入。僅靠應用程式先查後寫不足以維持唯一性,最終約束與衝突處理要由適合資料庫的原子操作保障。正常重送與不同內容衝突應有不同紀錄及處置。

去重保存期也影響結果。若只保留一天的ID,但設備可補送一週前事件,較舊重送可能再被計入。決定事件與身分保留政策時,要把最大補送期間、封存與重播需求一起考慮,而不是只按短期磁碟用量。

遲到資料回到正確區間再重建

重新排序後也檢查事件的合法狀態轉移。兩筆開始夾一筆結束,可能是遺漏、重啟或識別範圍錯誤,不能只按時間排整齊就認為完成重建。無法唯一配對的區間應保留不確定標記。

將去重後事件按可信的來源時間歸到報表區間,再使用明確排序規則重建狀態。結束事件先到、開始事件晚到時,先標區間不完整,待開始到達後重算。不要把先收到的結束事件丟掉,否則之後補齊也無法恢復。

若摘要已發布,晚到資料應觸發受影響區間的重算或修訂流程,保留舊版本與原因。一次重播應從去重後明細重建,或使用明確的差額更新;不能一面整段重算、一面又加上晚到值而重複計數。

Azure Stream Analytics的事件排序設定是特定產品範例,它可能依設定丟棄或調整超出容忍窗的事件。使用這類服務時,應保留原始來源時間及處置資訊,不能假設系統一定原封不動保存所有晚到資料。

完成後檢查輸入到明細再到摘要的件數關係。正常新事件增加有效筆數,完全相同的重送不增加,內容衝突進入待處理,晚到新事件回到其所屬區間。這四個結果應能各自重現並查看證據。

練習與常見問題

練習:A站世代7序號1收到兩次,A站世代8序號1收到一次,B站世代7序號1收到一次,且同身分內容一致。以本例複合身分規則,有三個不同事件、一筆重送。若只以序號1去重,會錯刪兩個真實事件。

失敗時先查事件ID是否在重送時改變、啟動世代是否可靠、空值與衝突是否被忽略,再查報表時間歸屬。資料量不對不一定是排序錯,兩類問題要按層定位。

問:相同時間與數值就是重複嗎?答:不是,可能是不同產品或同時發生的事件。

問:排序後可以刪收件時間嗎?答:保留它才能分析補送、延遲及資料何時可見。

問:唯一鍵能解決遲到嗎?答:它處理身分衝突,歸屬與重算是另一組規則。

問:ID一樣但值不同怎麼辦?答:保存衝突與依據,不能默認最後值一定正確。

參考:PostgreSQL 18 Constraints:唯一約束、主鍵及空值語意。

參考:Microsoft Azure Stream Analytics Event ordering:事件時間、收件時間及晚到資料策略。

延伸閱讀