簡體   English   中英

在MariaDB / MySQL中沒有鎖定刪除?`(InnoDB)

[英]DELETE without lock in MariaDB/MySQL?`(InnoDB)

據我所知, DELETE FROM ... WHERE在表上發出鎖定。

現在,我在MariaDB中有一個巨大的InnoDB表,其大小為1TB +,正在被使用,並且鎖定它直到整個數據庫被搜索到要刪除的行是沒有選擇的。

有沒有什么方法可以刪除匹配某些條件的行而不會在刪除時鎖定它?

以下是針對此案例的更多細節:

  • 服務器正在從Debian Stretch存儲庫運行MariaDB 10.1.22-3
  • 服務器有32 GB ram和innodb_buffer_pool_size = 20G
  • 數據庫的大小為1TB +,並且始終有許多活動的INSERTSELECT
  • 整個數據庫只包含2個表:
    • 一個表用於實際數據(基本上有一個類似data (BIGINT id, LONGTEXT data)的結構data (BIGINT id, LONGTEXT data) (其中data是JSON的一大塊。我知道這不是一個完美的關系數據庫模型,但JSON來自第三個派對,它非常復雜,可能隨時包含來自第三方的結構變更,恕不另行通知)
    • 還有一個表用於滿足SELECT的某種“索引”。 (簡化示例,這可能有像data_index (BIGINT id, INT userId, INT itemId, BIGINT timestamp)這樣的結構,所以我可以在userId和itemId上使用SELECT ,並加入實際數據。(timestamp是unix時間戳,以毫秒為單位) )
  • 就像我說的那樣,數據只能在有限的時間內存儲。 所以基本上現在我想創建一個每天運行一次的cronjob來刪除超過7天的行。

為了完成任務,我自然會想出這個簡單的查詢:

DELETE `data`, `data_index`
FROM `data_index`
LEFT JOIN `data` ON `data`.`id` = `data_index`.`id`
WHERE `timestamp` > (NOW() * 1000) - (7 * 24 * 60 * 60 * 1000)

但這可能會鎖定表格很長一段時間。 如何在鎖定表的情況下完成相同的任務,這樣數據庫仍可用於其他SELECTINSERT查詢?

不,如果不鎖定已檢查的行,則無法刪除。

但是,您可以通過在要搜索的timestamp列上創建索引來最小化檢查的行數。

這還將針對您可能嘗試在表的末尾插入的潛在行創建間隙鎖定 ,以確保新行不會影響DELETE。

在InnoDB中,像DELETE創建的普通寫鎖不會阻止讀取。 並發事務仍然可以讀取行 - 甚至是您要刪除的行。

普通的寫鎖不會鎖定整個表。 好吧,它使用意圖鎖來鎖定表,這意味着阻止其他表鎖,如ALTER TABLE或DROP TABLE所需的那些。 換句話說,在進行任何讀取或寫入操作時,不能對表進行ALTER / DROP操作。

你可能會喜歡我的演示文稿: InnoDB Locking用Stick Figures解釋

(NOW() * 1000) - (7 * 24 * 60 * 60 * 1000)看起來不像是有效時間。 它是20170519568613000 ,看起來像DATETIME和某種毫秒的混合。 也許你想要UNIX_TIMESTAMP() * 1000 - (7 * 24 * 60 * 60 * 1000) = 1494742589000

您希望刪除多少行? 如果它是一個大數字,那么考慮分區或刪除塊

也許我錯了,但是在https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html上我已經讀過它會使行鎖,而不是表鎖。

無論如何你可以試試

DELETE ... FROM ... WHERE ... LIMIT x

並根據需要執行多次。 在執行之間,其他查詢可以進入並最小化影響。 當然,在低負荷時間完成這項工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM