繁体   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