每当尝试从表中删除记录时出现错误1206

时间:2013-11-24 10:48:09

标签: mysql sql

我有一个包含超过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。

我会感激任何帮助。

2 个答案:

答案 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

这一切都很顺利,直到它说到

所见的剩余更新为600000
select 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 )中。

这个答案的要点是要了解它为什么会发生。并且任何读者都可以制作出符合他们需求的终端游戏解决方案(有时候,对系统变量,重新启动和祈祷进行无效的改变)。