在我的生产数据库中,警报相关的表是使用默认的“拉丁语”字符集创建的,因此,当我们尝试在表中插入日文字符时会出错。我们需要将表和列的默认字符集更改为 UTF8。由于这些表有大量数据,Alter 命令可能需要很长时间(在我的本地数据库中使用相同数量的数据需要 5 小时)并锁定表会导致数据丢失。我们能否计划一种机制将 Charset 更改为 UTF8,而不会丢失数据。
更改大型数据表的字符集的更好方法是什么?
在我的生产数据库中,警报相关的表是使用默认的“拉丁语”字符集创建的,因此,当我们尝试在表中插入日文字符时会出错。我们需要将表和列的默认字符集更改为 UTF8。由于这些表有大量数据,Alter 命令可能需要很长时间(在我的本地数据库中使用相同数量的数据需要 5 小时)并锁定表会导致数据丢失。我们能否计划一种机制将 Charset 更改为 UTF8,而不会丢失数据。
更改大型数据表的字符集的更好方法是什么?
您可以查看 Percona Toolkit::online-chema-change 工具:
pt-online-schema-change
它正是这样做的 - “在不阻塞读取或写入的情况下更改表的结构” - 有一些限制(仅限 InnoDB 表等)和涉及的风险。
我在 mysql 手册http://dev.mysql.com/doc/refman/5.1/en/alter-table.html上找到了这个:
在大多数情况下,ALTER TABLE 会制作原始表的临时副本。MySQL 等待其他正在修改表的操作,然后继续。它将更改合并到副本中,删除原始表并重命名新表。在执行 ALTER TABLE 时,其他会话可以读取原始表。在 ALTER TABLE 操作开始后开始的对表的更新和写入会停止,直到新表准备好,然后自动重定向到新表,没有任何失败的更新
所以是的 - 在这样做时尽量减少停机时间是很棘手的。这取决于您的表的使用情况,是否有更多的读/写?
我能想到的一种方法是使用某种复制。因此,创建一个使用 UTF-8 的新 Alert 表,并找到一种将原始表复制到新表而不影响可用性/吞吐量的方法。当复制完成(或足够接近)时,通过重命名来切换表?
当然,这说起来容易做起来难——如果可能的话,需要更多的学习。
当您设置复制发出停止从命令并更改表时,在其他机器或实例上创建数据库的复制副本。如果您有多个表,则在每次对话之间您可以考虑再次发出 start slave 以同步两个数据库。(如果您不这样做,同步可能需要更长的时间)当您完成转换时,复制的副本可以替换您的旧生产数据库并删除旧数据库。这是我发现减少停机时间的方法。