1. 程式人生 > SQL入門教學 >實戰2:如何使用軟刪除(邏輯刪除)

實戰2:如何使用軟刪除(邏輯刪除)

1. 前言

SQL Delete 一節中,我們介紹了 SQL 的基本刪除功能,今天我們將以分類實戰的角度來進一步學習 SQL 的刪除。

刪除是一個很危險的操作,試想一下如果開發人員不慎操作失誤,誤刪了一些資料,在資料未備份的情況下,該資料無法恢復,造成了損失絕對是致命的。

道路千萬條,安全第一條。因此為了保證資料的安全性,在真正的企業級應用中都會預設的採用邏輯刪除(軟刪除)的方式來處理資料刪除。

那麼既然軟刪除使用如此普遍,它究竟如何使用了?

2. 軟刪除與硬刪除

從邏輯的角度上來說,我們可以把刪除分為兩大類:軟刪除硬刪除

說明 描述
軟刪除 在邏輯上刪除,資料依然存在 會通過資料表上的某一欄位來表示,如deleted
硬刪除 在物理上刪除,資料被丟棄 無額外支援,直接被刪掉了

其實,在很多資料庫中,硬刪除也並非直接將資料從磁碟上丟棄,而是通過標誌位將該資料標誌為已刪除。由於資料庫是按頁來組織儲存資料的,如果硬刪除直接將資料從頁中丟棄的話,可能會引起資料頁的分裂和重組,這樣會大幅降低資料庫的效能。

但是硬刪除的資料可能會被後面新增的資料覆蓋,所以磁碟上也會真正的丟失掉該資料。

2.1 軟刪除實施方案

軟刪除是在程式層面上的刪除,在資料庫中資料仍然存在,軟刪除常見的有兩種實施方案:

  1. 整型欄位標誌位:在資料表增加一個deleted欄位來表示記錄是否被刪除,0

    表示未刪除,1表示已被刪除。

  2. 日期欄位標誌位:在資料表增加一個delete_time欄位來表示記錄是否被刪除,null表示未刪除,有日期表示已被刪除。

3. 實踐

接下來,我們以實踐的角度來看看軟刪除是如何實現的。

3.1 整型欄位標誌位

我們仍然以imooc_user表為例,並新增deleted作為邏輯標誌位。如下:

DROP TABLE IF EXISTS imooc_user;
CREATE TABLE imooc_user
(
  id int PRIMARY KEY,
  username varchar(20),
  age int,
  -- 以 deleted 欄位作為軟刪除標記位
deleted int NOT NULL DEFAULT 0 );

3.1.1 整型軟刪除操作

有了標誌位後,我們新增一條記錄:

INSERT INTO imooc_user(id,username,age) VALUES (1,'pedro',23);

新增成功後,記錄如下:

+----+----------+-----+---------+
| id | username | age | deleted |
+----+----------+-----+---------+
| 1  | pedro    | 23  | 0       |
+----+----------+-----+---------+

其中deleted欄位為0表示記錄正常,當有了標誌位後,我們每次查詢資料時都需要新增上標誌位,即:

SELECT * FROM imooc_user WHERE id = 1 AND deleted = 0;

當要刪除該記錄時,我們不能直接通過 Delete 來刪除了,而是通過 Update:

UPDATE imooc_user SET deleted = 1 WHERE id = 1;

軟刪除後,我們再次通過查詢語句SELECT * FROM imooc_user WHERE id = 1 AND deleted = 0;,發現已經查不到該記錄了。於是,記錄在邏輯上已經刪除了,可它仍在資料庫中。

這樣,就能在“刪除”資料的情況下保證資料的安全性。

3.2 日期欄位標誌位

修改一下imooc_user表:

DROP TABLE IF EXISTS imooc_user;
CREATE TABLE imooc_user
(
  id int PRIMARY KEY,
  username varchar(20),
  age int,
   -- 以 delete_time 欄位作為軟刪除標記位
  delete_time timestamp DEFAULT NULL
);

3.2.1 日期軟刪除操作

整體上與整形欄位標誌位相同,如下:

新增記錄:

INSERT INTO imooc_user(id,username,age) VALUES (1,'pedro',23);

查詢記錄:

SELECT * FROM imooc_user WHERE id = 1 AND delete_time IS NULL;

刪除記錄:

UPDATE imooc_user SET delete_time = NOW() WHERE id = 1;

你可能會覺得這有些麻煩,沒關係不少好用的 ORM 庫,如 Hibernate,Sequelize 均已經提供了軟刪除功能,你只需配置一下,就能直接呼叫API來達到軟刪除的效果。

4. 小結

  • 若無特殊需求,比如需要記錄刪除的具體時間,我們推薦使用整形欄位軟刪除,效能較好。
  • 軟刪除不會改變資料頁的分佈和排列,而硬刪除可能會破壞資料頁,從而降低查詢效能,因此在磁碟容量允許的情況下,首選軟刪除。