我们的公司(小型企业)最近在亚太地区开展了新业务,这要求我们在 MySQL 5.7 DB 中支持 4 位字符。
这个要求意味着我们需要将数据库从一种字符集转换为另一种字符集。
数据库表的大小从几行到 100GB 不等。有些表有许多外键和索引。偶尔会有一两个存储过程,但这些用一只手就能数得过来。
我们可以为此安排停机时间。
我们在 AWS RDS 中运行,为了获得最佳转换时间,我们决定拍摄快照,移动到可以使用的最大容量实例和最高配置 IO。这就像 r5.24xlarge 或具有 50,000 IOPS 的东西。
不幸的是,当我们测试这个时,使用 ALTER TABLE SET CHARSET 转换每个表需要超过 8-12 个小时...
虽然我们可以安排停机时间,但我们不能停机那么长时间。4 个小时可能已经超出了企业可接受的极限。
我们已经开始从一些表中修剪旧数据,但还远远不够。
这里的主要瓶颈是,无论我们一次运行多少个表转换、数据库的大小、存储分配或预配置的 IOPS,RDS 磁盘吞吐量峰值都会达到 350MB/s。事实上,IOPS 从未达到 50K,CPU/内存也很少。磁盘队列达到 10 左右,我认为这是因为吞吐量限制。
我们还尝试了 Aurora,但对于我们的情况来说,它实际上速度较慢。
有人知道我们如何才能进一步提高吞吐量或减少进行转换所需的时间吗?
答案1
如果您正在使用足够新的 MySQL 版本,并且不需要任何 utf8mb4 PRIMARY KEY
,则以下方法可能会有效。(请先在大表上进行彻底测试)
对于每个表:
- 添加与现有 utf8 列类似但具有 utf8mb4 和合适排序规则的 VARCHAR/TEXT 列。
- 添加一个触发器,当新数据进入时对任何 VARCHAR/TEXT 列执行以下步骤。
- 在表上运行 UPDATE 以将新列设置为旧列。
稍后,所有表都升级完毕后:
- 更改涉及列的任何索引
- 删除旧列。
这种机制存在一些潜在的严重问题:
- 具有不同字符集的 JOIN...ON 可能不使用索引。
- 我不确定这种机制是否会在没有表无法访问的严重时间的情况下发挥作用。
- 可能还有其他事情。
pt-online-schema-change——可能一次更改一个表,从而导致上述问题。
基于 STATEMENT 的复制(在 RDS 中可能不可用?)可能提供一种转换副本、继续复制以及(方便时)故障转移的方法。