mysql – 什么原因导致pt-online-schema-change减慢它通过表的进一步速度?
作者:互联网
我目前正在一个包含大约2300万行的表上运行模式迁移.这些行具有正常的主索引,我们正在运行MySQL 5.5.
迁移,添加几列,很快就开始了.它以很快的速度在大约3分钟内复制了前300万.接下来的3分钟大约需要20分钟.一夜之间,它在大约8小时内再做了900万次.
除了修改我愿意接受的副本延迟之外,我没有修改默认值 – 因此它遵循块时间并且旨在使每个副本在~0.5秒范围内.
当我正在运行带有PTDEBUG的工具时,我可以看到详细的输出,并且看起来操作在该范围内正确 – 但我不明白为什么它们变得越来越慢.在峰值时,它每秒大约有7000行,并且它正在慢慢地进一步下降,我们现在已经下降到~470,仍然有大约1500万行.
我有几个假设,但我不确定哪个是正确的,或者如何诊断它.
我的任何假设是否正确,我将如何识别?
>它是原始表上的索引 – 查询本身耗时太长.我假设它不是这个,因为SELECT不在主键上.
>这与插入过程有关.表越大,关于INSERT的“思考”就越多,因此这个过程需要更长的时间.
>某处存在硬件限制.顺便说一句,我们在RDS上运行3个副本.监控并不意味着我们目前正在遇到瓶颈.
这是匿名的CREATE TABLE语句:
CREATE TABLE `user_offer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`CreatedDate` datetime NOT NULL,
`A` int(11) NOT NULL,
`B` int(11) NOT NULL,
`C` int(11) NOT NULL,
`D` datetime DEFAULT NULL,
`E` datetime DEFAULT NULL,
`F` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`G` int(11) DEFAULT NULL,
`H` int(11) DEFAULT NULL,
`I` int(11) NOT NULL,
`J` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`K` tinyint(1) NOT NULL,
`L` tinyint(1) NOT NULL,
`M` tinyint(1) NOT NULL,
`N` tinyint(1) NOT NULL,
`O` int(11) NOT NULL,
`P` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`Q` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`R` tinyint(1) NOT NULL,
`S` tinyint(1) NOT NULL,
`T` int(11) DEFAULT NULL,
`U` tinyint(1) NOT NULL,
`V` int(11) DEFAULT NULL,
`W` datetime DEFAULT NULL,
`X` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`Y` tinyint(1) NOT NULL,
`Z` tinyint(1) DEFAULT NULL,
`AA` int(11) DEFAULT NULL,
`AB` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_CB147C66AAB016B8` (`I`),
KEY `IDX_CB147C6668D3EA09` (`J`),
KEY `L_idx` (`L`),
KEY `H_idx` (`H`),
KEY `IDX_CB147C6632A90D98` (`T`),
KEY `IDX_CB147C66F6CB3049` (`V`),
KEY `createdDate_idx` (`CreatedDate`),
KEY `consentedDate_idx` (`W`),
CONSTRAINT `FK_CB147C6632A90D98` FOREIGN KEY (`T`) REFERENCES `table_1` (`id`),
CONSTRAINT `FK_CB147C6668D3EA09` FOREIGN KEY (`H`) REFERENCES `table_2` (`id`),
CONSTRAINT `FK_CB147C66AAB016B8` FOREIGN KEY (`I`) REFERENCES `table_3` (`id`),
CONSTRAINT `FK_CB147C66F6CB3049` FOREIGN KEY (`V`) REFERENCES `table_2` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23448523 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
alter语句是:ADD AC VARCHAR(5)加上在AC,P和Q上添加索引.
解决方法:
猜测……更改缓冲区已满且溢出.
该操作正在构建11个二级索引.对于InnoDB,通过在buffer_pool的一部分(称为Change Buffer)中存储待办事项信息来“延迟”构建二级索引.
最终需要将“更改”刷新到磁盘.你的表可能比buffer_pool大得多,所以它可能会溢出.这里(大致)是如何为新表创建给定行的11个索引:
>将11条记录写入更改缓冲区.这样的记录(我猜)是二级密钥列加上主键列.
>检查溢出.如果没有空间(现在就是你的空间),请从磁盘读取一些索引块,将索引条目折叠到其中,将块排队以写回磁盘,并从更改缓冲区中释放索引条目.
最初所有11个索引都是空的,所以上面的过程是将大量的东西转储到磁盘上 – 非常有效.
随着处理的继续,索引变得越来越大,“更多条目的转储”效率降低,因为需要处理的块越多,每个块中的记录就越少.也就是说,每个读 – 修改 – 写步骤都会从更改缓冲区中释放越来越少的条目.
这反过来减慢了处理速度,pt-online-schema-change巧妙地变成了更小的块大小.
备择方案
>有时在构建表后重建索引会更好.但是,您可能不想这样做,因为它会导致停机.
>在5.6(以及5.7中的更多)中,可以执行许多ALTER,而对运行系统的影响非常小. 5.5现在是最老的支持版本;你应该考虑升级. (对于在线更改不适用的情况,Pt-online-schema-change仍然有用.)
>垂直分区 – 您可以考虑使用新列构建“并行”表,而不是向此表添加列.这通常可以在没有停机的情况下完成.虽然有些SELECT需要JOIN,但这不一定是性能负担.
标签:mysql,mysql-5-5 来源: https://codeday.me/bug/20190806/1604723.html