Mysql
以最少的鎖定刪除大量級聯記錄
我正在尋找一種從 MySQL 數據庫中清除大量邏輯刪除數據的策略。被刪除的記錄在一個相對較小的表中,但是在多個引用表上被很多ON DELETE CASACDE記錄引用,這使得刪除過程非常緩慢且耗時,在此期間一些較小但更頻繁訪問的表是,顯然,已鎖定(這些是 InnoDB 表)。
由於這些清除在高負載數據庫上定期發生,因此我試圖找出清除這些數據的最佳策略,同時對其他程序的影響最小,即對父表的鎖定最少。
舉個例子,我有一個類似這樣的表結構:
+------------+ +------------+ +------------+ +-------------+ | accounts | | users | | messages | | attachments | +------------+ +------------+ +------------+ +-------------+ | id | | id | | id | | id | | name | | account_id | | user_id | | message_id | | is_deleted | | name | +------------+ +-------------+ +------------+ +------------+ users.account_id REFERENCES accounts.id ON DELETE CASCADE messages.user_id REFERENCES users.id ON DELETE CASCADE attachments.message_id REFERENCES messages.id ON DELETE CASCADE
假設每個帳戶有幾十個使用者,每個使用者有數千條消息,並且每條消息可能有幾十個附件和其他相關數據(例如標籤、元數據等) - 刪除一個帳戶將導致數万或數十萬條記錄被刪除,跨越多個表。
在這種情況下清除數據時採取什麼好的策略?
您可以從某些腳本中批量刪除:
1)標記帳戶刪除(似乎你現在正在做)
2)在腳本中-為某個標記的帳戶選擇一個使用者並將其刪除-正如您期望每個帳戶有許多使用者,這將僅刪除所有消息和附件的一小部分,因此應該足夠快
3)對給定帳戶的剩餘使用者重複2,一次一小批,其他程序可以在鎖之間完成工作
4)刪除帳戶 - 沒有使用者這麼快
如果刪除一個使用者仍然需要很長時間,您可以向下一層並刪除批量說 1000 條消息,然後刪除所有使用者的帳戶,現在沒有消息又這麼快了。
問題是您失去了 ACID 屬性,因為它全部在多個事務中執行-> 在送出第一次刪除後您無法回滾,並且在兩者之間執行的其他查詢將看到使用者的部分數據(消息/使用者的不完整列表取決於您的刪除粒度)。但是只有您可以說這對您來說是否是一個真正的問題,或者如果 is_deleted=1 意味著該帳戶不再在任何地方使用,因此它是安全的。