聊一聊 MYSQL 資料的真刪和假刪

2021-10-12 05:00:39 字數 4325 閱讀 1089

簡單做個小白文描述。

真刪, 我們就不展開了。

該篇文章其實主要是想聊聊 這個假刪 - 邏輯刪除 。

既然是對某張表做了假刪, 使用  status , 那麼在一些業務 查詢裡面 , 切記切記一定不能忘了,只要使用到 『 假刪 』的資料表,那麼需要帶上  status=0 .

驗重, 字面意思就是說資料唯一, 而這個資料的唯一保證 ,我們常規地首先是在**層面做唯一校驗,然後在資料庫層面也做唯一設定。

為什麼說 存在問題?

按照咱們的風格,舉個例子來看看:

首先我們現在有一張用於儲存企業enterprise資訊的表 , 業務上簡單理解,需要保證企業唯一,也就是企業名 name唯一(簡單舉個例子,具體看專案業務需求) 。

enterprise表

idname

address

status    (刪除標識,0未刪除 ,1 已刪除)

1小目標jcccc公司

象牙塔0

2test公司

夢想國度1 

保證name的唯一,那麼在 企業資料新增時, 按照常規來說我們需要做驗重處理。

select  id  from enterprise where name= ' ***x' ;
看到這裡, 可能已經有小夥伴有不一樣的看法了, 這個查詢的sql是否要帶上刪除標識?

select  id  from enterprise where name= ' ***x'  and status = 0 ;
這裡也就是指的是, 被執行了假刪的資料,是否還需要加入 驗重的校驗邏輯裡?

其實,不同的業務場景,規則肯定不需要。 例如上面例子裡面介紹的企業資訊表, 那麼如果企業資訊進行假刪後, 後面再一次進行企業資訊錄入時, 企業的名字肯定還是不會變化的。

那麼這時候,如果對所謂的 假刪資料 stauts=1 還掛鉤上,那麼就有些不符合常理了,

也就是說,這裡的假刪不能影響業務,在業務上其實就是已經真正刪除掉了。

select  id  from enterprise where name= ' ***x'  and status = 0 ;
ok,這麼一看,假刪的驗重問題似乎已經考慮齊全了,就這麼操作。

但是,目前來說也僅僅是**層面,呼叫sql時做的處理。  那往往很多時候, 在資料庫表建立的時候也需要對資料唯一字段進行唯一索引的建立

於是乎我們其實還需要考慮一下以下這個引申出來的問題:

回到剛剛例子中的  enterprise表 :

idname

address

status  (刪除標識,0未刪除 ,1 已刪除)

1小目標jcccc公司

象牙塔0

2test公司

夢想國度1

上邊說了下,我們需要保證企業資訊唯一,保證企業名 name 的唯一。

那麼,按照常規,name欄位的

唯一索引

(name_index )不可或缺 ,需要建立。

但是,此時這張表其實在驗重的時候,進行的邏輯判斷 是需要 帶上條件 status的。

那麼問題就出現了, 對於資料表的真正唯一來說,

其實是 name + status  這兩個字段同時保證唯一時, 資料才算是唯一。

也就是說唯一索引需要公升級為

唯一組合索引 

name欄位 & status欄位  (name_status_index).

到這裡, 好像是這麼乙個意思。 

這樣的唯一組合索引, 跟**層面的校驗規則似乎保持了一致的驗重邏輯處理。

保證了嗎? 能這樣建立嗎?

然而並不然! 

是的, 這個問題的介紹描述 轉折確實有點多了。 不過我就是想這麼地表達出 乙個 針對乙個問題的處理、設計解決方案, 需要一步步每個環節都進行把控。

直接看 enterprise表 的模擬資料 :

idname

address

status  (刪除標識,0未刪除 ,1 已刪除)

1小目標jcccc公司

象牙塔0

2test公司

夢想國度

1可以看到 test公司 這條資料的status是 1 , 那麼也就是進行了 所謂的假刪 ,邏輯刪除。

那麼再次建立時, 我們允許建立, 因為在有效資料內 (status=0) ,資料唯一即可,所以表內資料出現:

idname

address

status  (刪除標識,0未刪除 ,1 已刪除)

1小目標jcccc公司

象牙塔0

2test公司

夢想國度13

test公司

夢想國度

0這麼一看,id為3 的資料 在表內 存在合情合理, 跟id為2 的 被假刪資料 ,隔離得很好,沒有什麼問題。

但是, 再想想,這時候,管理員又把id為 3的資料 進行了 假刪。

會出現什麼情況?

沒錯如果我們做了唯一組合索引,那麼 再次進行邏輯刪除時, 問題出現,唯一組合索引 不允許 再次 存入   name 為 test公司、status 為 1 的資料,因為之前存在過了

那這時候,死局了。   

不設定索引了。 僅僅在**層面做 stauts=0 的有效資料 驗重算了。

帶來的不好影響:

資料庫層面不做唯一攔截,那就會允許存在有誤資料。

引入乙個新的字段 delete_uuid , 這個字段 作為 唯一組合索引 的成員  ,name_deleteuuid_index. 

那麼表結構將會變成:

idname

address

status  (刪除標識,0未刪除 ,1 已刪除)

delete_uuid

1小目標jcccc公司

象牙塔0

z2831a82-de87-c078-94bf-3dfd909292b00

2test公司

夢想國度

1null

3test公司

夢想國度

0e6831a82-de87-4078-94bf-4ed909292b00

怎麼使用呢, 可以看到 現在的組合唯一索引是 name & delete_uuid ,。

新增資料驗重時, 查詢加上條件 status =0 and delete_uuid !=null   保證有效資料內的唯一性。

然後是針對刪除操作, 進行邏輯假刪時, 把status改為1 ,並 設定 delete_uuid 為null。

(估計有些看官,看到這裡會有疑惑, 如果資料 name為test公司 ,刪除建立再刪除,那麼產生了兩條 name一樣且 delete_uuid 也都是null 的資料,資料庫允許麼? 這就需要給有疑惑的看官科普一下null 這個東西的知識了,可以看下下面這篇:

mysql 唯一索引的字段值 允許多個null值存在嗎 ?   

回歸話題內容,

這麼一來,即使出現id 為3 和id為2 這種資料場景,需要進行刪除時,也不會因為組合索引的唯一性無法進行刪除。

帶來的不好影響:

複雜度提高了;

多了乙個字段,那麼一些查詢、刪除時,就需要考慮到這個欄位的使用;

邏輯刪除的實現上做改變。  本來常規的是 把status從 0 改為 1 ;

那麼改為 從 原表 把執行邏輯刪除的資料, 遷移插入到歷史表 ,

這樣原表可以一直保證 name 字段 唯一索引的校驗即可。  

帶來的不好影響:

既然出現了歷史錶用於單獨儲存 假刪除的資料, 那麼意味著 儲存 同個業務資料表其實 一共有兩張表 。

我們再回到邏輯刪除這個東西的出現, 既然要進行邏輯刪除,那麼意思就是說,這個資料在一定的情況下,是不允許直接刪除,會存在 '恢復' 的情況。

那麼也就是說,如果有這種恢復的場景 就需要 考慮到兩張表的使用操作了。

額外,如果就比如本文中 企業表, 假如 進行邏輯刪除的資料需要加入一些資料統計分析業務, 那麼 兩張表的資料都需要使用到,隨之很多業務的實現也會因此而變得不那麼直接。

聊一聊MySQL裡的鎖和MVCC

在乙個高併發的資料庫系統裡,可能會遇到多個事務同一時刻修改某條資料的情況,這樣就產生了資源衝突,解決衝突就需要用到鎖。一 鎖一說到鎖,就可能會聯想到樂觀鎖 悲觀鎖 共享鎖 讀鎖 排他鎖 互斥鎖 寫鎖 行級鎖 表級鎖 等一堆名詞,那它們之間到底有什麼區別和聯絡呢?其實很簡單,樂觀鎖和悲觀鎖是一種加鎖的...

聊一聊大資料的問題和缺陷

多虧了 大資料和雲計算 可以讓企業使用超級計算機的力量。而人們面臨的問題是用來分析和應用大資料的工具通常有乙個致命的缺陷。人們進行的大部分 資料分析 都是基於錯誤的模型,這意味著錯誤是不可避免的。當人們誇大的期望超過其能力時,後果可能是可怕的。如果大資料不是如此巨大,這不會是乙個問題。考慮到人們擁有...

No 1 聊一聊資料獲取和爬蟲

為什麼要把資料獲取 爬蟲放在一起來聊呢?居士是想成為一名資料科學家的!資料科學家就要具備很多的技能,什麼統計學 資料探勘 資料倉儲 大資料計算 資料視覺化等等。但是,首先我們要有資料,沒有資料我們玩什麼?想要玩資料,我們就要來聊一下資料獲取,資料獲取有很多途徑,爬蟲算是其中最自力更生的技能了,而實現...