做軟刪除的工程師都覺得自己很聰明——數據不丟、審計過關、老板滿意。直到那個被刪掉的賬號想重新注冊,數據庫直接甩你一臉唯一約束沖突。
開發者Akmal最近就栽在這。用戶刪號半年后回來,填完郵箱點提交,系統報錯:該郵箱已存在。問題是,這郵箱明明"刪"了,記錄還在庫里躺著,唯一索引不認賬。
這事詭異在哪?大多數數據庫的NULL值不參與唯一性比較。換句話說,把deleted_at設成NULL能繞過約束,但刪過的記錄你得填時間戳——于是死鎖了:要軟刪除就得有值,有值就占著坑不讓新人用。
PostgreSQL的解法叫部分唯一索引,只在deleted_at IS NULL時生效。MySQL 8.0.13之后支持函數索引,也能曲線救國。Akmal的原話很扎心:「我以為軟刪除是最佳實踐,沒想到是最佳埋雷實踐。」
更諷刺的是,這坑在Stack Overflow躺了十幾年,框架文檔里幾乎不提。團隊規模小的時候沒人注意,等到用戶量上來,遷移成本已經高到想重寫。
現在Akmal的方案是復合索引加狀態字段,刪掉的記錄郵箱字段直接清空。歷史數據另存一張表,查詢時UNION。不完美,但至少不會讓凌晨三點的告警再響。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.