在较大的mySQL表上进行选择会激发所有连接,以切换到等待处理程序提交的状态

问题描述

我有一个大约90Gb的InnoDB表。我把它淘汰了。因此,只有我自己对其进行操作,并且我不会冒险锁定问题。

我正在寻找一种选择和分组依据的策略,以将数据摘要保留在另一个表中,然后删除所有89Gb。

我尝试的所有事情似乎都占用了太多资源:几分钟后,所有连接都陷入等待处理程序提交的状态,这非常糟糕。 (即使没有其他用户查询此表) 我怀疑内存有问题

到目前为止,我想到的最好的就是这个

CREATE PROCEDURE insert_into_backup_summary()
BEGIN
    DECLARE d DATE DEFAULT DATE("2020-07-07");
    WHILE d <= "2020-10-16" DO
        INSERT INTO backup_summary
        SELECT NOW() backupDate,userId,DATE(createdDate) `date`,COUNT(id) count 
          FROM backup
          WHERE DATE(createdDate) >= d
            AND DATE(createdDate) < DATE_ADD(d,INTERVAL 10 DAY)
          GROUP BY userId,`date`;
        SET d = DATE_ADD(d,INTERVAL 10 DAY);
    END WHILE;
END;

但是它仍然会在10-15分钟后阻止所有连接。

我只尝试了一个简单的SELECT * FROM backup,几秒钟后它就阻塞了,这使我认为问题出在SELECT查询上

有什么想法可以在此过程中保持良好的记忆力吗?

解决方法

听起来您的循环正在引起系统资源的大量争用。当我看到线程在COMMIT上阻塞时,通常是因为I / O已饱和。换句话说,您正在强制从磁盘读取太多数据,以致没有其他机会使用磁盘。

我注意到您的条件将导致循环的每次迭代进行表扫描。当您使用诸如DATE(createdDate) >= d之类的条件时,即使您在该列上有索引,也无法在createdDate上使用索引。只要您在索引列上使用函数,就会发生这种情况。因此,它必须检查表中的每一行,而不仅仅是日期范围之间的行。

要解决此问题,请在不将其放入函数内的情况下引用这些函数:

WHERE createdDate >= d AND createdDate < DATE_ADD(d,INTERVAL 10 DAY)

这对于选择日期范围应该同样有效,并且将允许使用索引。那应该减少对磁盘的需求。

您可能还希望使循环在两次迭代之间停下来。您可以这样做:

    SET d = DATE_ADD(d,INTERVAL 10 DAY);
    DO SLEEP(10);
END WHILE;

如果其他线程被阻止,这应该为其他线程使用磁盘存储提供机会。

除此之外,我想问一下您正在使用哪种存储类型?因为如果您过时或存储缓慢,则在处理90GB的表时应考虑到这一点。


发表您的评论

@@ innodb_log_file_size:50331648 @@ innodb_buffer_pool_size:4294967296

您的日志文件大小为50MB,即default。我建议您将其增加到至少1GB。在我公司,我们将其设置为1GB作为起点,对于大多数生产应用程序来说已经足够了。

我现在想的是,当您如此迅速地写入大量记录时,您正在填充innodb日志文件。当日志文件已满时,innodb必须阻止提交,直到缓冲池的一部分刷新到表空间,从而释放部分日志文件以供覆盖。增大日志文件的大小应允许更多写入,然后再进入此状态。

您的缓冲池大小为4GB,考虑到服务器上有128GB RAM,这似乎很小。您可能应该将其增加很多,但必须记住服务器上可能需要RAM的其他进程。

我有一个关于调优选项的演示。我在MySQL 5.5是当前版本时编写了演示文稿,但这仍然是非常准确的建议。 https://www.slideshare.net/billkarwin/mysql-55-guide-to-innodb-status

此博客的信息也非常好: https://www.percona.com/blog/2016/10/12/mysql-5-7-performance-tuning-immediately-after-installation/

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...