實戰2:如何使用軟刪除(邏輯刪除)
1. 前言
在 SQL Delete 一節中,我們介紹了 SQL 的基本刪除功能,今天我們將以分類
和實戰
的角度來進一步學習 SQL 的刪除。
刪除是一個很危險的操作,試想一下如果開發人員不慎操作失誤,誤刪了一些數據,在數據未備份的情況下,該數據無法恢復,造成了損失絕對是致命的。
道路千萬條,安全
第一條。因此為了保證數據的安全性,在真正的企業級應用中都會默認的采用邏輯刪除(軟刪除)的方式來處理數據刪除。
那么既然軟刪除使用如此普遍,它究竟如何使用了?
2. 軟刪除與硬刪除
從邏輯的角度上來說,我們可以把刪除分為兩大類:軟刪除
和硬刪除
。
說明 | 描述 | |
---|---|---|
軟刪除 | 在邏輯上刪除,數據依然存在 | 會通過數據表上的某一字段來表示,如deleted |
硬刪除 | 在物理上刪除,數據被丟棄 | 無額外支持,直接被刪掉了 |
其實,在很多數據庫中,硬刪除也并非直接將數據從磁盤上丟棄,而是通過標志位將該數據標志為已刪除。由于數據庫是按頁來組織存儲數據的,如果硬刪除直接將數據從頁中丟棄的話,可能會引起數據頁的分裂和重組,這樣會大幅降低數據庫的性能。
但是硬刪除的數據可能會被后面添加的數據覆蓋,所以磁盤上也會真正的丟失掉該數據。
2.1 軟刪除實施方案
軟刪除是在程序層面上的刪除,在數據庫中數據仍然存在,軟刪除常見的有兩種實施方案:
-
整型字段標志位:在數據表增加一個
deleted
字段來表示記錄是否被刪除,0
表示未刪除,1
表示已被刪除。 -
日期字段標志位:在數據表增加一個
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. 小結
- 若無特殊需求,比如需要記錄刪除的
具體時間
,我們推薦使用整形字段軟刪除,性能較好。 - 軟刪除不會改變數據頁的分布和排列,而硬刪除可能會破壞數據頁,從而降低查詢性能,因此在磁盤容量允許的情況下,首選軟刪除。