日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

數據庫模型設計——歷史與版本設計

系統 2101 0

在企業數據庫設計中,經常會遇到一個需求,就是希望把操作之前的數據保留下來,能夠看到操作之前是什么數據,操作之后是什么數據。對于這種需求,我們可以使用保留歷史數據或者使用版本來實現。

為了能夠保留歷史數據,在版本設計時有以下方案:

?

一、使用版本號

版本號是一種常見的版本設計方案,就是在要進行歷史數據保留的表上面增加一個版本號字段,該字段可以是DateTime類型,也可以是int類型,每進行數據操作時,都是創建一個新的版本,版本是只增不減的,所以只需要拿到最大一個版本號,就能得到最新的業務數據。

版 本號除了能夠用于留存歷史數據外,還有一個功能就是避免并發編輯操作。比如我們有一個對象A,當前的版本是1,兩個用戶同時打開了該對象的編輯頁面,進行 數據更改。先是甲用戶提交更改,這個時候系統把對象的ID和版本進行查詢,發現要修改的數據最新版本是1,所以成功修改,保存了對象A的新版本2。這個時 候用戶乙也提交了修改。系統把對象的ID和版本1進行查詢,發現要修改的數據最新版本是2,不符合要求,所以拒絕用戶乙的修改。用戶乙只有刷新界面,拿到 最新的版本2,再進行修改。

ID 單號 金額 版本號
1 EXP123 100 1

在使用版本號的情況下,對單據的金額進行修改,修改后創建新的版本號2:

ID 單號 金額 版本號
1 EXP123 100 1
2 EXP123 120 2

二、使用生效、失效時間

保存歷史數據的第二辦法是使用生效失效時間來表示一個版本。要進行歷史數據記錄的表增加“生效時間”“失效時間”兩個字段,兩個字段不允許為空。對于剛創 建的數據,生效時間是創建該數據的時間,失效時間是9999-12-31?,F在對這條數據進行了修改,那么我們只需要將當前時間設置為上一個版本的失效時 間,同時創建一條新數據,生效時間是當前時間,失效時間是9999-12-31即可。

ID 單號 金額 生效時間 失效時間
1 EXP123 100 2013/9/1 15:30:00 9999/12/31 23:59:59

比如上面一條單據,是2013-9-1創建的,后來在2013-9-9 15:00:00對該單據進行修改,將金額從100修改為120,保存時創建的新數據如下:

ID 單號 金額 生效時間 失效時間
1 EXP123 100 2013/9/1 15:30:00 2013/9/9 15:00:00
2 EXP123 120 2013/9/9 15:00:00 9999/12/31 23:59:59

使用了生效、失效時間后,我們可以查詢任意時刻數據庫中數據的值,只需要把要查詢的時刻傳入,然后between 生效時間 and 失效時間即可。

使用前兩種方案都需要一個業務主鍵來標識具體的一個業務數據。如果我們要記錄的實體沒有明確的“單號”、“訂單號”這類的業務主鍵該怎么辦?我們可以使用創建數據時的數據庫主鍵作為業務主鍵。

員工ID 姓名 生日 業務ID 版本號
1 張三 1984/12/29 1 1

比如我們有個員工表,記錄員工基本信息,在創建張三這個員工的數據時,其在數據庫的ID為1,那么可以將其業務ID也設置為1。接下來對張三的屬性進行更改,記錄了版本,那么就會創建新的版本,其主鍵“員工ID”會變化,但是其業務主鍵“業務ID”始終是1,不會變化的。

員工ID 姓名 生日 業務ID 版本號
1 張三 1984/12/29 1 1
2 張三 1985/1/9 1 2

使 用前面兩個方案雖然能夠很好的記錄歷史數據,但是每次修改數據都會導致新版本生成保存,所以每個版本的ID都是新的,所以必須有一個業務主鍵來標識一個實 體,這里的兩個例子“單號”就是其業務主鍵。主鍵的變動使得所有關聯的對象都得變動,從而形成連鎖效應,使得各個關聯的對象也生成新的版本。比如我們有個 訂單系統,里面有訂單表和訂單明細表?,F在我們要對訂單的修改記錄歷史版本,所以增加了生效時間和實效時間,并使用訂單號作為業務主鍵。現在有一個訂單 A,下面有100條明細,如果要對訂單進行修改,將某一條明細的屬性進行修改,從而導致整個訂單的變化,那么我們就需要創建新的訂單數據行,由于主鍵變 動,所以訂單明細都需要變動,所以100條明細都需要創建新的版本,新版本的訂單明細中,“訂單ID”指向了新的版本的訂單數據的ID。

image

這樣的設計造成的問題就是訂單明細表會極速膨脹,如果一個訂單有1000條明細,我們只是修改了訂單本身的屬性,并不修改訂單明細,也會造成對這1000條明細做Copy,然后保存。那怎么辦呢?我們可以使用以下辦法:

1.對訂單明細建立版本字段,將版本的粒度細化到訂單明細,而不是訂單。訂單與訂單明細不存在數據庫級的外鍵關系,只存在業務級的外鍵關系。也就是說訂單明細表中增加生效時間、失效時間之外,還需要增加“訂單號”這個字段,用于表名該明細是屬于哪個訂單的。

image

我 們這么修改后,如果訂單對象進行了修改,訂單明細沒有修改(比如改了一下收件人信息),那么只需要在訂單表中生成新的一行數據,訂單明細不會Copy生成 新的數據。如果我們對某一條訂單明細進行了更改(比調整了單價、數量)那么只需要對具體修改的那條訂單明細進行更改,而不需要對整個訂單的所有明細進行更 改。

使用這種設計后,查詢訂單及其明細,需要對兩個表執行生效失效時間的過濾,而且明細的獲取是通過訂單號去取,而不是通過訂單ID去取。

將版本控制的粒度細化到訂單明細時,后臺程序的邏輯也會更加復雜。用戶在界面上操作的是訂單對象,系統會將整個修改后的訂單對象傳到后臺,后臺程序需要對每個訂單項進行對比,如果發現訂單項進行了修改,那么就會調用生成新版本訂單明細的方法。

2.使用單獨的歷史表

這是另外一種實現歷史版本記錄的方法:

三、使用單獨的歷史表

使 用歷史表其實就是建立完全相同Schema的表(當然,也可以添加更多的字段用于記錄額外的歷史版本信息),該表只保留歷史版本的數據。這有點像一個歸檔 邏輯,所有歷史版本我們認為都應該是不經常訪問的,所有可以扔到單獨的表,對于現有生效的版本,仍然保留在原表中,如果需要查詢歷史版本,那么就從歷史表 中查詢。

使用單獨的歷史表有以下好處:

  • 業務數據表的數據量不會因為歷史版本記錄而膨脹。因為歷史數據都記錄到了另外一個表中,所以業務數據表只記錄了一份數據。
  • 業務數據表的Schema不需要調整,增加額外的版本字段。由于對原有數據表不做Schema變更,所以原有查詢邏輯也不用更改。對于一個現有的數據庫設計,在增加歷史數據記錄功能時更簡單。
  • 業務數據表可以直接進行update操作,不會生成新的ID。由于ID不會變,所以我們并需要業務主鍵應用到程序邏輯中。

使 用歷史表記錄歷史版本主要是要對數據操作方法(增加、刪除、修改)進行修改,使得每次數據操作時,先在歷史表中留痕,然后再進行數據操作。另外就是對查詢 歷史版本功能進行修改,因為歷史數據在另外一個表中,所以對于的SQL是不一樣的。當然,我們也可以創建歷史版本數據庫,里面保存了所有的歷史表。

數據庫模型設計——歷史與版本設計


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 六盘水市| 金阳县| 曲周县| 曲阜市| 东乡县| 老河口市| 孙吴县| 星子县| 枣强县| 牙克石市| 洞口县| 治县。| 梅州市| 凤城市| 昌吉市| 阳山县| 武夷山市| 潍坊市| 马关县| 枣强县| 诸城市| 兖州市| 三原县| 静安区| 弥渡县| 新疆| 多伦县| 上林县| 黄浦区| 朝阳市| 双峰县| 上虞市| 阿尔山市| 赫章县| 南城县| 城固县| 张家口市| 扶余县| 祁东县| 宜城市| 达拉特旗|