![](/img/trans.png)
[英]How to prevent MySQL InnoDB setting a lock for delete statement through JDBC
[英]DELETE without lock in MariaDB/MySQL?`(InnoDB)
據我所知, DELETE FROM ... WHERE
在表上發出鎖定。
現在,我在MariaDB中有一個巨大的InnoDB表,其大小為1TB +,正在被使用,並且鎖定它直到整個數據庫被搜索到要刪除的行是沒有選擇的。
有沒有什么方法可以刪除匹配某些條件的行而不會在刪除時鎖定它?
以下是針對此案例的更多細節:
innodb_buffer_pool_size = 20G
INSERT
和SELECT
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時間戳,以毫秒為單位) ) 為了完成任務,我自然會想出這個簡單的查詢:
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)
但這可能會鎖定表格很長一段時間。 如何在不鎖定表的情況下完成相同的任務,這樣數據庫仍可用於其他SELECT
和INSERT
查詢?
不,如果不鎖定已檢查的行,則無法刪除。
但是,您可以通過在要搜索的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.