锁的总数超过锁表大小

我正在MySQL中运行一个报告。 其中一个查询涉及将大量的行插入临时表中。 当我尝试运行它时,我得到这个错误:

错误代码1206:锁的数量超过锁表大小。

有问题的查询是:

create temporary table SkusBought( customerNum int(11), sku int(11), typedesc char(25), key `customerNum` (customerNum) )ENGINE=InnoDB DEFAULT CHARSET=latin1; insert into skusBought select t1.* from (select customer, sku, typedesc from transactiondatatransit where (cat = 150 or cat = 151) AND daysfrom07jan1 > 731 group by customer, sku union select customer, sku, typedesc from transactiondatadelaware where (cat = 150 or cat = 151) AND daysfrom07jan1 > 731 group by customer, sku union select customer, sku, typedesc from transactiondataprestige where (cat = 150 or cat = 151) AND daysfrom07jan1 > 731 group by customer, sku) t1 join (select customernum from topThreetransit group by customernum) t2 on t1.customer = t2.customernum; 

我读过,更改configuration文件来增加缓冲池的大小将有所帮助,但是这没有任何作用。 解决这个问题的方法是什么?或者作为一个临时的解决方法或者是一个永久性的解决scheme?

编辑:改变了查询的一部分。 不应该影响它,但我做了一个查找replace所有,并没有意识到它搞砸了。 不影响这个问题。

编辑2:添加typedesc到t1。 我改变了查询,但不是在这里。

这个问题可以通过为MySQLvariablesinnodb_buffer_pool_size设置更高的值来解决。 innodb_buffer_pool_size的默认值是8,388,608

要更改innodb_buffer_pool_size的设置值,请参阅下面的设置。

  1. 从服务器find文件my.cnf 。 对于Linux服务器,这将主要在/etc/my.cnf
  2. innodb_buffer_pool_size=64MB行添加到此文件
  3. 重新启动MySQL服务器

要重启MySQL服务器,你可以使用以下2个选项中的任何一个:

  1. 服务mysqld重启
  2. /etc/init.d/mysqld restart

引用锁的总数超过锁表大小

我find了另一种解决方法 – 使用表锁。 当然,如果您需要同时更新表格,它可能不适合您的应用程序。

请参阅:尝试使用LOCK TABLESlocking整个表,而不是InnoDB的MVCC行级locking的默认操作。 如果我没有弄错,“locking表”是指存储MVCC实现的行和版本标识符的InnoDB内部结构,它具有标识行在语句中被修改的位,并且具有6000万行的表,可能超过分配给它的内存。 LOCK TABLES命令应该通过设置表级锁而不是行级来缓解这个问题:

 SET @@AUTOCOMMIT=0; LOCK TABLES avgvol WRITE, volume READ; INSERT INTO avgvol(date,vol) SELECT date,avg(vol) FROM volume GROUP BY date; UNLOCK TABLES; 

MySQL公司北美地区社区关系经理Jay Pipes

从MySQL文档 (您已经阅读,因为我看到):

1206(ER_LOCK_TABLE_FULL)

锁的总数超过锁表大小。 为了避免这个错误,增加innodb_buffer_pool_size的值。 在个别应用程序中,解决方法可能是将大型操作分解为更小的部分。 例如,如果发生大型INSERT错误,请执行几个较小的INSERT操作。

如果增加innodb_buffer_pool_size不起作用 ,那么只需按照粗体部分的指示,将INSERT分割为3.跳过UNION并创build3个INSERT,每个都有一个JOIN到topThreetransit表。

如果您已经正确地构build了表,以便每个表都包含相对唯一的值,那么执行此操作的密集方式就是执行3个单独的insert-into语句,每个表使用1个,每个insert使用join-filter,

 INSERT INTO SkusBought... SELECT t1.customer, t1.SKU, t1.TypeDesc FROM transactiondatatransit AS T1 LEFT OUTER JOIN topThreetransit AS T2 ON t1.customer = t2.customernum WHERE T2.customernum IS NOT NULL 

对另外两个表重复这一点 – 复制/粘贴是一个很好的方法,只需更改FROM表名。 **如果您试图阻止SkusBought表中的重复条目,则可以在WHERE子句之前的每个节中添加以下连接代码。

 LEFT OUTER JOIN SkusBought AS T3 ON t1.customer = t3.customer AND t1.sku = t3.sku 

– 然后是WHERE子句的最后一行 –

 AND t3.customer IS NULL 

你的初始代码使用了许多子查询,而且UNION语句可能很昂贵,因为它将首先创build它自己的临时表来填充来自三个独立源的数据,然后再插入到你想要的表中,查询来过滤结果。

在Windows中:如果你有MySQL的工作台。 转到服务器状态。 在我的情况下find运行服务器文件的位置是:

 C:\ProgramData\MySQL\MySQL Server 5.7 

打开my.ini文件并findbuffer_pool_size。 将值设置为高。 默认值是8M。 这是我如何解决这个问题