当使用mysql delete commnad时,锁的总数超过了锁表大小

时间:2015-06-06 07:32:34

标签: mysql database innodb

我在Centos 6.4 64位操作系统上使用mysql server v5.1.73。我有一个大约17m记录的表,它的大小约为10GB。这个表的mysql引擎是innodb 这个表有10列,其中一列是' date'其类型是日期时间。我想用mysql删除特定日期的记录'删除'命令。

delete
from table
where date(date) = '2015-06-01'
limit 1000

但是当我运行此命令时,我收到一个错误'锁的总数超过锁表大小'。我之前和当我更改innodb_buffer_poolsize时遇到此问题,它会解决问题,但这次甚至增加了这个数量,问题仍然存在。
我尝试了许多技巧,比如将限值改为100或甚至1条记录,但它不起作用。我甚至将innodb-buffer-poolsize增加到20GB,但没有任何改变 我还阅读了这些链接:
"The total number of locks exceeds the lock table size" Deleting 267 Records
The total number of locks exceeds the lock table size
但他们并没有解决我的问题。我的服务器有64GB RAM 另一方面,我可以在特定日期不使用过滤器时删除记录:

delete
from table
limit 1000

我也可以毫无问题地选择当天的记录。
任何人都可以帮我这个吗? 我很感激任何帮助来解决这个问题。

2 个答案:

答案 0 :(得分:1)

请勿使用date(date),否则无法使用INDEX(date)。而只需使用date并使索引以date开头。

More ways to do a chunking delete

答案 1 :(得分:0)

WHERE子句中的

date(date)要求数据库在运行时为数据库中所有17m行计算该列的值-DB将为17m行逐行创建date(date),然后创建表扫描(没有索引)这1700万行以得出结果集。这是您资源不足的地方。

您需要删除计算列的用法,这可以通过几种不同的方法解决。

将您的比较更改为: 日期> ='2015-06-01 00:00:00'和日期<='2015-06-01 23:59:59'

这现在将直接命中日期列上的索引(我假设您在此列上有一个索引,只是原始查询不会使用它)

另一种解决方案是在DATE类型的表中添加一列,并将每个DATETIME的DATE永久存储在该列中(并显然为新的DATE列添加索引)。这样一来,您无需指定时间范围,即可运行只希望检查DATE部分的任何查询。如果您当前还有其他查询使用date(date),则比起将时间范围添加到查询中,最好只包含一个仅包含日期的列(将时间范围添加到查询中比较好)。像这里的SELECT或DELETE,但可能不适用于涉及JOIN,GROUP BY等的其他查询。