数据库
首页 > 数据库> > mysql – 什么原因导致pt-online-schema-change减慢它通过表的进一步速度?

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