我有一个包含超过4000万条记录的表。我想用sql查询删除大约150000条记录:
DELETE
FROM t
WHERE date="2013-11-24"
但是我收到错误1206(锁的总数超过了锁表大小)。 我搜索了很多并更改缓冲池大小:
innodb_buffer_pool_size=3GB
但它不起作用。 我也试图锁定表格,但也不起作用:
Lock Tables t write;
DELETE
FROM t
WHERE date="2013-11-24";
unlock tables;
我知道一个解决方案是拆分删除过程,但我希望这是我的最后一个选择。 我使用的是mysql服务器,服务器操作系统是centos,服务器Ram是4GB。
我会感激任何帮助。
答案 0 :(得分:3)
您可以在删除时使用Limit
,并尝试一次批量删除10,000条记录中的数据:
DELETE
FROM t
WHERE date="2013-11-24"
LIMIT 10000
您还可以包含ORDER BY子句,以便按照子句指定的顺序删除行:
DELETE
FROM t
WHERE date="2013-11-24"
ORDER BY primary_key_column
LIMIT 10000
答案 1 :(得分:0)
发生此错误有很多古怪的方法。我会尝试列出一两个,也许这个类比适用于某些人在某个时候阅读此内容。
在更大的数据集上,即使将innodb_buffer_pool_size
更改为更大的值,也可以在没有足够的索引来隔离where子句中的行时遇到此错误。或者在某些情况下使用主要索引(参见this)和Roger Gammans的评论:
来自(innodb的5.0文档): -
如果没有适合您的语句的索引,MySQL必须扫描 整个表来处理语句,表的每一行 变为锁定,这反过来阻止其他用户的所有插入 表。创建好的索引非常重要,以便您的查询能够完成 不必要地扫描很多行。
通过这个简单的模式可以看出这个错误如何发生并且很难解决:
CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` int(11) NOT NULL,
`campusId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ix_stu_cam` (`camId`)
) ENGINE=InnoDB;
一张包含5000万行的表格。 FK没有显示,不是问题。此表最初用于显示查询性能也不重要。然而,在以1M行为单位初始化thing
= id
时,我必须在块更新期间执行限制以防止出现其他问题:
update students
set thing=id
where thing!=id
order by id desc
limit 1000000 ; -- 1 Million
这一切都很顺利,直到它说到
所见的剩余更新为600000select count(*) from students where thing!=id;
为什么我这样做count(*)
源于重复
错误1206:锁的总数超过了锁表大小
我可以继续降低上述更新中显示的LIMIT,但最后我会在计数中留下1200 !=
,问题就会继续。
为什么会继续?因为系统在扫描这个大表时填充了锁表。当然,它可能会内部隐含交易"在我看来,已经将最后1200行更改为相等,但由于锁表填满,实际上会在没有设置的情况下中止事务。这个过程会陷入僵局。
插图2 :
在这个示例中,我们说我有50万行表的 288行,可以在上面显示更新。由于描述了最终游戏问题,我经常会发现运行此查询的问题两次:
update students set thing=id where thing!=id order by id desc limit 200 ;
但我不会有这些问题:
update students set thing=id where thing!=id order by id desc limit 200;
update students set thing=id where thing!=id order by id desc limit 88 ;
有很多方法可以解决这个问题,包括但不限于:
一个。在列上创建另一个索引,表明数据已更新,可能是boolean
。并将其纳入where
子句。然而,在巨大的表格上,创建一些临时索引可能是不可能的。
B中。使用尚待清理的id's
填充第二个表可能是另一种解决方案。加上和update with a join模式。
℃。动态更改LIMIT值,以免导致锁定表超限。当没有更多行进行UPDATE或DELETE(您的操作),尚未达到LIMIT,并且锁定表填满了无效的扫描以获得更多根本不存在时(见上文),可能会发生超限在 Illustration2 )中。
这个答案的要点是要了解它为什么会发生。并且任何读者都可以制作出符合他们需求的终端游戏解决方案(有时候,对系统变量,重新启动和祈祷进行无效的改变)。