1. 程式人生 > >如何設計一張事件記錄流水錶(版本2)

如何設計一張事件記錄流水錶(版本2)

在設計完 版本1的事件記錄表 後,大家就開始馬不停蹄寫程式碼去新增事件記錄資料。

版本1:事件表

流水ID

id

物件ID

obj_id

系統編碼

sys_code

網點編碼

area_code

操作者工號

operator_id

源狀態

source_status

事件編碼

event_code

事件描述

event_desc

目標狀態

target_status

建立時間

create_time

123456 A111 TEST_SYSTEM XXX 0123777 初始 001 列印 列印完成 2018-09-06 18:33:35
123457 A111 TEST_SYSTEM QQQ 0123666 列印完成 002 核銷 核銷完成 2018-09-07 12:05:43

改進:   

       在記錄事件的源狀態StateA時,一開始的做法是獲取其他業務資料表中某物件的當前狀態,來設定事件記錄表的源狀態。但在一些業務場景下,對於同一個事件編碼event_code,雖然目標狀態StateB是一樣的,但是源狀態StateA會有很多種情況,此時如果通過業務資料表的當前狀態來設定源狀態的值,會十分繁瑣,而且業務程式碼上需要知道當前狀態,不夠透明。

       基於上面情況,我們不再從其他業務資料表中獲取某物件的當前狀態,而是依賴於事件記錄表前後的資料,從版本1的表中,可看到,在按照建立時間排序的前提下,ID為123457的源狀態(列印完成),就是上一條記錄ID為123456的目標狀態(目標狀態)。所以想要設定某物件的源狀態,只要找到該物件在事件記錄表中的上一條記錄的目標狀態即可  

       但這種方案,嚴重依賴於上一條記錄,當有多個節點同時都往這個事件記錄表插入資料時,要對這“上一條記錄”的資料進行鎖定,需要採用分散式鎖或者資料庫鎖的機制

再次改進:

       認真想想,由於事件記錄表是按照物件做動作時按時間順序插入的,只要保證時間順序,其實可以不需要記錄源狀態,每條資料的目標狀態,也相當於它上一條資料的源狀態

。因此,我們對事件表進行改造,形成版本2:

版本2:事件表

流水ID

id

物件ID

obj_id

系統編碼

sys_code

網點編碼

area_code

操作者工號

operator_id

事件編碼

event_code

事件描述

event_desc

目標狀態

target_status

建立時間

create_time

123456 A111 TEST_SYSTEM XXX 0123777 001 列印 列印完成 2018-09-06 18:33:35
123457 A111 TEST_SYSTEM QQQ 0123666 002 核銷 核銷完成 2018-09-07 12:05:43

由於事件記錄表本身的時間順序的特性,所以版本2的表基本可以滿足我們記錄物件全生命週期的需求。還是版本1的需求,比如我們想知道物件A111從列印完成狀態到核銷完成狀態所花費的時間,用sql更容易就實現了:

開始時間:

SELECT create_time AS begin_time FROM db_event_report WHERE obj_id = 'A111' AND target_status = '列印完成';

結束時間:

SELECT create_time AS end_time FROM db_event_report WHERE obj_id = 'A111' AND target_status = '核銷完成';

然後將上面兩條sql查詢出來的begin_time和end_time套入以下sql函式,即可算出相隔的分鐘數

SELECT TIMESTAMPDIFF(MINUTE, begin_time, end_time);

至此,我們的事件記錄流水錶設計結束。