Mysql

以最少的鎖定刪除大量級聯記錄

  • January 28, 2018

我正在尋找一種從 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 意味著該帳戶不再在任何地方使用,因此它是安全的。

引用自:https://dba.stackexchange.com/questions/112387