![](/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.