将巨大的数据库从Latin1转换为UTF8?

时间:2013-06-10 10:50:12

标签: php mysql utf-8 character-encoding latin1

我们有一个用PHP编写的系统,这些系统多年来已经发展得相当大。数据库是MySQL(InnoDB表),目前有超过12GB的数据,有数百个表,其中许多表有超过1200万个记录!

问题是,很多表/列(但不是全部)都在latin1中,而且我们(很明显)会出现存储外来字符的问题。

我们将所有表格/文本列转换为UTF8的最佳方式是什么?停机时间最短?

该系统每周7天,每天24小时由数百人使用,因此长时间停机确实不是一种选择。

是否有任何方式成功完成此操作而没有大量的停机时间,是否有任何明显的事情我们需要注意?

我知道我们需要设置以下内容才能使我们的应用程序使用utf-8:

  • <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  • ini_set('default_charset', 'utf-8');
  • SET NAMES utf8
  • 在上传文件之前在我们的IDE中编码为UTF8的文件

我已经阅读了其他各种帖子,但是每个人似乎都在建议不同的方法,有些人说它需要完整的数据库转储/恢复......这意味着需要数小时的停机时间。

那么最好的方法是什么?

1 个答案:

答案 0 :(得分:0)

你希望做一些可行的事情,但非常很难,也有风险。放弃聪明:没有什么可以让这很容易的神奇之处。一方面,您需要将停机时间与人工成本和数据丢失风险进行权衡。如果您停机15小时,您的人工成本可能会高出十倍。

是否可以为保证检索自特定日期/时间以来添加或更改的每一行的每个表写一个SELECT查询,并快速完成?如果是这样,请为每个表编写此查询并将其保留在手边。如果没有,则无法使用此方法。

您可以按表格执行此表格。

小桌子不需要做太多事情;当你的申请在非高峰时段上班时,你可能会这样做。只需转换列。

如果您从未更新过较大的表,则可以使用所需的charset和默认排序规则为相关列创建这些表的副本。然后,您可以使用INSERT ... SELECT复制数据。 (http://dev.mysql.com/doc/refman/5.1/en/insert-select.html)最后,在一些停机时刻,您可以重命名生产表,然后为新表提供生产表名称。您可能需要在几千行的数据块中执行此操作,以使InnoDB的事务完整性系统不会耗尽服务器的RAM。

最后,您必须处理大型和不断变化的表格。再次,使用INSERT ... SELECT复制表,再次以InnoDB事务不会暂停应用程序操作或破坏RAM的方式。这里的目的是在特定日期/时间创建您的表格快照。

然后,关闭生产。使用您的handy-dandy查询从开始时间开始选择所有插入和更改的行,并将它们插入/更新到目标表中。然后重命名生产表,并为目标表提供生产表的名称,然后重新开始生产。你应该能够很快地做到这一点。

如果我是你,我会制作你的实时制作数据库的临时副本,并在实际操作之前排练这个程序的每一步。例如,您将在InnoDB中遇到外键约束的问题;你需要能够仔细研究这些。

实际上,如果我是你,我不会尝试这样做。这就像飞机飞行时更换飞机的发动机一样。怎么可能出错? :-)相反,我会产生预定的Web应用程序停机时间以完成此转换。即使在这种情况下,您也应该在登台服务器上尝试整个事情,然后才能上线。