mysql邏輯刪除真的不是一個好的設計


轉自:https://www.jianshu.com/p/f37281576585

在互聯網公司中數據的積累是非常重要的,所以就有了邏輯刪除這樣的設計。所謂邏輯刪除就是在表中加入類似is_deleted字段,將刪除操作變成更新操作。當is_deleted=1時就代表這條記錄已經刪除,這樣做的好處非常明顯,數據不會消失,對於商業分析來說“被刪除”的數據也非常有價值。

但事情往往不會這么簡單,硬幣的另一面是邏輯刪除引入了一點點復雜度,大部分讀操作都需要過濾掉處於刪除狀態的記錄,過濾操作要么在數據庫層面完成,要么在應用中完成,通常這樣的復雜度是完全可以接受的,但是對於MySQL而言,邏輯刪除的設計還會導致常用的unique key失效,原因非常簡單,已經刪除的數據仍然存在,所以在設計unique key的時候程序員不得不將is_deleted字段與應用要求unique的字段一起放入unique key中,這樣is_deleted=0的記錄就不會與is_deleted=1的字段沖突了,這是符合邏輯的,is_deleted=0的記錄之間會發生沖突,但這正是unique key的本意,所以也是符合邏輯的,但是問題在於is_deleted=1的記錄之間也會發生沖突,這可能就不符合邏輯了,為什么呢?簡單來說這樣的設計在unique key存在的情況下不允許unique key字段相同的記錄被刪除兩次以上,這對於應用來說是一個很大的限制。

而實際上很多互聯網公司在數據庫設計規范中都加入了邏輯刪除的強制規定,從商業分析的角度來說這樣做沒有問題,但問題留給了開發人員,我們只能在unique key與邏輯刪除之間做一個排他的選擇嗎?但是unique key都放棄了,我們用的還是關系型數據庫嗎?不過兩者都兼得的辦法還是有的,我個人認為有三種方案,依次是1不靠譜方案,2靠譜方案,3推薦方案

1. 不靠譜方案:放棄使用MySQL

朋友們,看完這個小標題你完全可以選擇跳過這一段。
但為什么說這樣可以解決問題呢,因為我們需要的其實是這樣一個功能:unique key where is_deleted=0,對嗎?我們其實不關心is_deleted=1的記錄是否重復,遺憾的是MySQL並不支持這個功能,但是並非所有的數據庫都不支持這個功能,比如SQL Server就可以。

2. 靠譜方案:增加delete_token字段

是的,除了is_deleted字段我們還需要增加一個delete_token字段來完成邏輯刪除這個設計。定義的方式是這樣的,delete_token varchar(32) not null default 'NA',使用方式是:首先is_deleted字段不再參與unique key,而是將delete_token加入unique key中,在刪除時,is_deleted字段更新成1,同時delete_token字段更新成一個32位的uuid,這樣刪除的記錄因為uuid的存在就不會沖突了,問題解決了。但為什么我不推薦使用這個方案呢?因為MySQL對於unique key的長度是有限制的,對於InnoDB來說這個限制是767 bytes, 對於MyISAM這個限制是1000 bytes,假設你使用了utf8mb4 字符編碼,那么delete_token就會占據128 bytes,這其實引入了另一個隱含的限制。

3. 推薦方案: 使用數據倉庫

回到邏輯刪除的初衷,我們需要的是將數據沉淀下來用於商業分析,而邏輯刪除的設計將數據分析與應用邏輯雜糅在了一起,而實際上應用使用的MySQL並不適合做數據分析,又平白增加了應用的復雜度,這樣的設計最終兩頭都不討好。所以還是讓應用數據庫與數據倉庫發揮各自的功能吧,應用數據庫與數據倉庫都可以通過監聽數據操作指令來自由的更新數據,至於刪除操作,對於應用數據庫來說就是物理刪除,但對於數據倉庫來說可以只是一條更新操作。

總結:

為什么我們要使用MySQL這樣的數據庫呢?因為我們關心的不止是數據本身還有數據之間的關系,而MySQL的這樣的數據庫天生就是為這些關系設計的,從目前來說這些關系當中並不包含刪除關系。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM