0

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

问题是,很多表/列(但不是全部)都在 latin1 中,我们(显然)在存储外来字符时遇到了问题。

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

该系统有数百人 24/7 全天候使用,因此长时间停机确实不是一种选择。

有没有什么方法可以在没有大量停机时间的情况下成功地做到这一点,有什么明显的事情我们需要注意吗?

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

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

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

那么最好的方法是什么?

4

1 回答 1

0

你希望做一些可能的事情,但非常困难,也很冒险。放弃聪明:没有什么神奇的东西可以让这件事变得简单。一方面,您需要在停机时间与人工成本和数据丢失风险之间进行权衡。您的人工成本可能会比停机 15 小时高出十倍。

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

您可以逐表执行此操作。

小桌子不需要做太多事情;您可能可以在您的应用程序在非高峰时间运行时执行它们。只需转换列。

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

最后,您必须处理大型且不断变化的桌子。再次使用 , 复制表,以确保INSERT ... SELECTInnoDB 事务不会暂停您的应用程序的操作或耗尽您的 RAM。此处的目的是获取某个日期/时间的表格快照。

然后,关闭生产。使用方便的查询选择自开始时间以来所有插入和更改的行,并将它们插入/更新到目标表中。然后重命名您的生产表,并为您的目标表指定生产表的名称,然后重新开始生产。您应该能够相当快地做到这一点。

如果我是你,我会为你的现场制作数据库制作一个临时副本,并在现场制作之前排练此过程的每一步。例如,您将在 InnoDB 中遇到外键约束问题;您需要能够仔细处理这些问题。

事实上,如果我是你,我不会尝试这样做。这就像在飞机飞行时更换飞机的发动机。会出什么问题?:-) 相反,我会招致预定的 Web 应用程序停机时间来完成此转换。即使在这种情况下,您也应该在上线之前在登台服务器上尝试整个事情。

于 2013-06-10T11:42:45.373 回答