use*_*253 3 mysql database mariadb
据我所知,DELETE FROM ... WHERE在桌子上发出了锁。
现在,我在MariaDB中有一个正在使用的巨大的InnoDB表,大小为1TB +,正在使用它,直到在整个数据库中搜索要删除的行之后才锁定它。
有什么方法可以删除符合特定条件的行而不在删除发生时锁定它?
这是此情况的更多详细信息:
innodb_buffer_pool_size = 20GINSERT并且SELECT始终有很多active 和。data (BIGINT id, LONGTEXT data):(其中data有大量JSON。我知道这不是一个完美的关系数据库模型,但是JSON来自第三方,它非常复杂,并且可能包含第三方随时更改结构,恕不另行通知)SELECTs的某种“索引” 。(简化的示例,其结构可能类似于data_index (BIGINT id, INT userId, INT itemId, BIGINT timestamp),因此我可以SELECT在userId和itemId上使用,并加入实际数据。(时间戳是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)
Run Code Online (Sandbox Code Playgroud)
但这可能会锁定表很长时间。我怎么能完成相同的任务,而不锁定表,所以数据库仍然是其他功能SELECT和INSERT查询?
不,如果不锁定检查的行,则无法删除。
但是您可以通过在timestamp要搜索的列上创建索引来最大程度地减少检查的行数。
这还将针对您可能尝试在表末尾插入的潜在行创建间隙锁,以确保新行不会影响DELETE。
在InnoDB中,普通的写锁(如DELETE创建的锁)不会阻止读取。并发事务仍然可以读取行,甚至是您要删除的行。
普通的写锁不会锁定整个表。好吧,它用意图锁来锁定表,目的锁只是防止其他表锁,例如ALTER TABLE或DROP TABLE所要求的那些。换句话说,当表正在进行任何读取或写入操作时,您不能更改/删除该表。
您可能喜欢我的演示文稿:InnoDB Locking用Stick Figures解释了。
也许我错了,但在https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html上我读到它会产生行锁,而不是表锁。
无论如何你可以尝试
删除...从...哪里...限制x
并根据需要执行多次。在执行之间,其他查询可以进入并最大限度地减少影响。当然,请在低负载时间进行这项工作。