Mysql 锁的总数超过了锁表的大小
我正在MySQL中运行一个报告。其中一个查询涉及在临时表中插入大量行。当我尝试运行它时,会出现以下错误: 错误代码1206:锁的数量超过了锁表的大小 有关问题包括:Mysql 锁的总数超过了锁表的大小,mysql,sql,Mysql,Sql,我正在MySQL中运行一个报告。其中一个查询涉及在临时表中插入大量行。当我尝试运行它时,会出现以下错误: 错误代码1206:锁的数量超过了锁表的大小 有关问题包括: create temporary table SkusBought( customerNum int(11), sku int(11), typedesc char(25), key `customerNum` (customerNum) )ENGINE=InnoDB DEFAULT CHARSET=latin1; insert i
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;
我已经读到,更改配置文件以增加缓冲池大小将有所帮助,但这没有任何作用。解决这个问题的方法是什么,临时解决方法还是永久解决方法
编辑:已更改查询的一部分。不应该影响它,但我做了一个查找替换所有,并没有意识到它搞砸了。不影响问题
编辑2:将typedesc添加到t1。我在查询中更改了它,但没有在这里更改。来自(如我所见,您已经阅读了):
1206(ER\U锁\U桌满)
锁的总数超过了锁表的大小。要避免此错误,请增加innodb_buffer_pool_size的值。在单个应用程序中,解决方法可能是将大型操作分解为较小的部分例如,如果大插入发生错误,请执行几个较小的插入操作。
如果增加innodb\u buffer\u pool\u大小没有帮助,那么只需按照粗体部分的指示将插入内容拆分为3。跳过联合并进行3次插入,每个插入都与topThreetransit表连接。我找到了另一种解决方法-使用表锁。当然,它可能不适合您的应用程序—若您需要同时更新表的话 见: 尝试使用
LOCK TABLES
锁定整个表,而不是InnoDB的MVCC行级锁定的默认操作。如果我没有弄错的话,“锁表”指的是InnoDB内部结构,该结构存储MVCC实现的行和版本标识符,其中有一个位标识正在语句中修改的行,表中有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;
杰伊·派普斯,
Community Relations Manager,北美,MySQL Inc.如果您已经正确地构造了表,使每个表都包含相对唯一的值,那么执行此操作的不太密集的方法是执行3个单独的insert into语句,每个表1个,每个insert都有连接筛选器-
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表名即可。
**如果试图防止SKUSBUY表中出现重复条目,可以在WHERE子句之前的每个部分中添加以下联接代码
LEFT OUTER JOIN SkusBought AS T3
ON t1.customer = t3.customer
AND t1.sku = t3.sku
-然后是WHERE子句的最后一行-
AND t3.customer IS NULL
您的初始代码使用了许多子查询,UNION语句可能会很昂贵,因为它首先创建自己的临时表来填充来自三个独立源的数据,然后再插入到所需的表中,同时运行另一个子查询来过滤结果。可以通过为MySQL变量设置更高的值来解决此问题
innodb\u缓冲区\u池\u大小
。innodb\u buffer\u pool\u size
的默认值为8388608
要更改innodb\u buffer\u pool\u size
的设置值,请参阅下面的设置
my.cnf
。对于Linux服务器,这将主要位于/etc/my.cnf
innodb\u buffer\u pool\u size=64MB
添加到此文件在windows中参考:如果您有mysql workbench。转到服务器状态。查找正在运行的服务器文件的位置(在我的示例中是):
C:\ProgramData\MySQL\MySQL Server 5.7
打开my.ini文件并找到缓冲池大小。将该值设置为高。默认值为8M。
这就是我如何解决这个问题的方法值得一提的是,用于此设置的数字是以字节为单位的-找到了困难的方法 我正在使用MySQL工作台运行MySQL windows。 转到服务器>服务器状态 顶部显示配置文件:“path”(
C:\ProgramData\MySQL\…\my.ini
)
然后在文件“my.ini”中按control+F并查找缓冲池大小。
将该值设置得更高,我建议使用64MB(默认值为8MB)
通过转到实例>启动/关闭>停止服务器(然后稍后再次启动服务器)重新启动服务器
在我的例子中,我无法从表中删除条目。首先,可以使用sql命令显示全局变量,如'innodb_buffer%'
检查缓冲区大小
解决方案是找到您的my.cnf
文件并添加
[mysqld]
innodb_buffer_pool_size=1G取决于您的数据和机器
下面的答案并不直接回答OP的问题。然而,
我在这里添加这个答案是因为这个页面是
您可以通过谷歌搜索“锁的总数超过了锁表的大小”。
如果正在运行的查询正在分析跨越数百万行的整个表,则可以尝试while循环,而不是更改配置中的限制
while外观会将其分解成碎片。下面是一个在DATETIME索引列上循环的示例
#放下
删除表(如果存在)
新表;
#创建(稍后我们将添加键)
创建表
新表
(
数值INT(11),
行id VARCHAR(255),
行值VARCHAR(255),
行日期时间
);
#换药
分隔符//
#创建过程
创建过程do_repeat(当前循环中的日期时间)
开始
#每周循环一次直到现在()。如果仍然出现锁定错误,请将“周”更改为“天”等较短的时间。
当前循环日期=当前循环日期和
行日期<当前循环日期
key_buffer_size=64M
read_buffer_size=64M
read_rnd_buffer_size=128M
innodb_log_buffer_size=10M
innodb_buffer_pool_size=256M
query_cache_type=2
max_allowed_packet=16M