刪庫不必跑路,談資料庫刪除設計

2021-10-03 10:38:57 字數 4212 閱讀 6659

凡是做業務邏輯系統, 總是離不開對刪除邏輯的處理.

本文論述重點是偽刪除, 即欄位標示狀態, 這是在一些中小型系統開發中的單據等較重要資料的主流做法.

但在此之前, 不妨先將常見刪除策略列舉一下:

1、資料庫設定級聯

這個我沒太懂是怎麼回事, 不過網上也說缺點較多, 很少用到, 在此就不考慮了

2、觸發器控制

– 本文所寫sql預設資料庫均為mysqlcreate triggertg_bf_insert_t_product_onlybefore insert ont_productfor each row begininsert into t_product_only (p_id,only_code) values (new.p_id,concat(new.group_code,』,』,new.p_code)) ;end;create triggertg_af_delete_product_onlyafter delete ont_productfor each row begininsert into t_product_deleted (p_id,group_code,p_code) values (old.p_id,old.group_code,old.p_code);delete from t_product_only where p_id=old.p_id;end;

優點是**業務邏輯簡單化, 且可以使用unique index,

缺點是對於一些級聯資料的恢復不好控制, 如主表單和明細表單, 另在表結構變更的時候, 對於觸發器的維護也是一件需要注意的事情.

字段標示狀態/偽刪除(下文中將統稱為偽刪除)

即用狀態表示已刪除,如status=-1或者is_del=1,

之所以說是中小型系統開發的主流做法, 是因為對於重要資料, 為了控制風險, 不會直接將資料刪除, 而使用觸發器前面的缺點也說了, 維護十分不易.

中小型系統本來就有邏輯變更頻繁, 以及資料量不會太高(單據數量幾百萬上千萬, 但很少上億)的特點, 權衡之下, 偽刪除往往成為首選.

即使是偽刪除, 也有幾種不同的設計方式, 以下以財務系統中常常使用到的記賬憑證為例, 介紹下幾種偽刪除的設計方案, 及實際中應當如何選擇.

以下是現實生活當中的一張記賬憑證.

由可以看出, 傳統的記賬憑證, 在資料庫設計中, 至少需要兩種表: 憑證主表和憑證明細表.

憑證主表記錄憑證日期, 憑證字(如記), 憑證數(如右上角的1號)等資訊,

憑證明細需要記錄摘要, 會計科目, 借貸方向/借方金額/貸方金額(這三個內容在資料庫表中至少需要儲存2個).

實際憑證設計中, 可能還需要考慮輔助核算等資訊, 本文簡化處理不考慮這些.

由於憑證比較重要, 多數情況都是原始資訊源(即不是可從其他資料中推導出的冗餘), 故選擇偽刪除是較常見的.

狀態設計欄位的選擇

如前文所述, 對於偽刪除欄位的選擇, 一般有兩種:

1.將憑證的常見狀態全都放在乙個欄位中, 包含已儲存status=0, 已審核status=1, 已刪除status=-1;

2.將已刪除單獨設為乙個字段, 如is_del, 刪除狀態時為0, 偽刪除狀態時為1.

第一種選擇, 好處是狀態字段只有乙個, 且恰好憑證在已審核狀態下是不允許被刪除的, where約束起來比較簡單.

– voucher_month表示憑證月份,記賬憑證均是以月為基本週期的-- voucher_mark表示憑證字+憑證數的一種冗餘,和憑證月聯合起來用以表示某一公司的一張唯一記賬update fnc_voucherset status=-1where company_id=1001and voucher_month='2019-01』and voucher_mark='記-1』and status=0

第二種選擇, 好處是將刪除狀態與正常的審批流程狀態區分開, 使得兩種邏輯得以解耦, 還有一種好處, 下文中會有提及.

– is_audited是是否已審核的意思update fnc_voucherset is_del=1where company_id=1001and voucher_month='2019-01』and voucher_mark='記-1』and is_audited=0and is_del=0

雖然第一種選擇的sql看起來更簡短, 但個人還是建議第二種選擇.

唯一索引的設計協同

設計資料庫**時, 一般建議是每一張資料庫**至少需設定乙個唯一索引, 個別情況還需要設計多個唯一索引. 偽刪除帶來的狀態標識字段增加, 可能會給唯一索引的設計帶來一些影響.

當憑證不考慮偽刪除的時候, 其唯一索引的設計方式如下:

alter table fnc_voucheradd unique key uk_voucher_cmm (company_id,voucher_month,voucher_mark);

當使用者允許憑證斷號時, 如在』記-7』和』記-9』之間允許存在乙個空的憑證號時,以上的唯一

索引仍能正常發揮作用.

但當使用者不允許憑證斷號(至少不允許自動斷號,可以增加手動憑證彌補斷號)時, 上面的唯

一索引就不再符合邏輯. 當』記-8』憑證已偽刪除時, 如果再增加一張同月的』記-8』憑證,

無疑會報duplicate key錯誤.

為了消除這種問題, 就需要將刪除資訊體現在唯一索引中.

這就是我建議將刪除狀態單獨設定為乙個欄位的另乙個原因: 當憑證被刪除時,

不將is_del設為1, 而改為id值:

update fnc_voucherset is_del=idwhere company_id=1001and voucher_month='2019-01』and voucher_mark='記-8』and is_audited=0and is_del=0

這樣, 唯一索引就可設計為:

alter table fnc_voucheradd unique key uk_voucher_cmmd (company_id,voucher_month,voucher_mark,is_del);

對於均放在乙個欄位中的設計, 當然也可考慮將刪除後的狀態值設定為id的負值:

update fnc_voucherset status=-idwhere company_id=1001and voucher_month='2019-01』and voucher_mark='記-8』and status=0

只是這樣做, 又會更進一步增加刪除與正常流程的耦合性, 給以後的設計帶來較大的困擾, 是不很建議這樣做的. 只有當已經將刪除設計為單字段混合狀態時, 才考慮使用這種方法.

對憑證明細的影響

前文所述的重點, 都是在對憑證主表上, 而一旦考慮到憑證明細, 就又回出現新的問題.

查詢憑證明細表的時候, 有兩種選擇:

1.根據主表的id查詢;

select summary,subject_code,debit_amount,credit_amountfrom fnc_voucher_detailwhere company_id=1001and voucher_id=12345-- 此sql理論上可以不在約束條件中加company_id限制,加只是為了格式統一

2.根據主表的憑證標識來查詢;

select summary,subject_code,debit_amount,credit_amountfrom fnc_voucher_detailwhere company_id=1001and voucher_month='2019-01』and voucher_mark=『記-8』

每種都有各自的優勢, 就筆者個人而言, 習慣使用第二種: 根據主表的憑證表示查詢憑證明細, 但這就產生衍生了乙個新的問題:

當乙個憑證偽刪除時, 且又生成了乙個與已刪除憑證標識相同的新憑證, 則新憑證就會共享已刪除憑證的明細, 導致明細邏輯的錯誤!

解決這個問題, 就必須要在憑證明細上也增加刪除狀態標識, 當偽刪除憑證時, 同時也對憑證明細進行偽刪除處理.

update fnc_voucher_detailset is_del=idwhere company_id=1001and voucher_month='2019-01』and voucher_mark='記-8』and is_del=0;

select summary,subject_code,debit_amount,credit_amountfrom fnc_voucher_detailwhere company_id=1001and voucher_month='2019-01』and voucher_mark='記-8』and is_del=0;

如果使用根據id關聯查詢, 當然可以規避這種情況, 只是用id需要關聯查詢, 一般會帶來一些效率上的差異.

刪庫不必跑路,自己動手MySQL資料恢復,真香

今天專案上需要對mysql進行資料修復,通過比較各種方案和工具,準備使用binlog2sql工具進行 資料閃回 具體怎麼使用呢,安排。以恢復某個庫的某個表為例,準備兩個一模一樣地mysql,安裝上,推薦用yum rpm方式安裝,否則,配置起來能否一次性安裝成功,看運氣了。源庫 mysql 5.7.3...

刪庫跑路 你應該看看雲資料庫

本文由techeek發表於資料訂閱專欄 傳統企業在建設資料庫初期,不僅建設伺服器,還要保證資料庫能夠穩定和可靠的執行。當業務資料增長到一定大小的時候,就需要增加伺服器cpu及記憶體以及磁碟相關資源。為了保證伺服器的穩定性,還需要制定相關制度及體系,定製資料庫的架構,防止資料庫被攻擊,確保資料庫安全穩...

刪庫跑路 你應該看看雲資料庫

本文由techeek發表於資料訂閱專欄 傳統企業在建設資料庫初期,不僅建設伺服器,還要保證資料庫能夠穩定和可靠的執行。當業務資料增長到一定大小的時候,就需要增加伺服器cpu及記憶體以及磁碟相關資源。為了保證伺服器的穩定性,還需要制定相關制度及體系,定製資料庫的架構,防止資料庫被攻擊,確保資料庫安全穩...