【问题标题】:Exporting / Importing MySQL to/from different character sets向/从不同字符集导出/导入 MySQL
【发布时间】:2015-04-16 17:40:58
【问题描述】:

这很简单。

我有一个使用 DEFAULT CHARSET=utf8; 运行表的数据库; 排序规则设置为 utf8_general_ci。

一切正常。使用此数据库的应用程序可以保存从普通话(中文)到瑞典语的任何内容,一切都很好。

但是。 db 有以下设置。

Variable_name   Value
character_set_client    utf8
character_set_connection    utf8
character_set_database  latin1
character_set_filesystem    binary
character_set_results   utf8
character_set_server    latin1
character_set_system    utf8
character_sets_dir  /usr/share/mysql/charsets/

如您所见,由于未知原因,数据库将 character_set_databasecharacter_set_server 设置为 latin1

这不会对运行它的应用程序造成问题,所以我们在那里很好,但是每当我们导出和导入时,都会将所有 charachter_set_* 变量设置为 utf8 或 utf8mb4(这似乎成为新常态),这使我们不得不为与数据库的每个会话进行额外的 SET NAMES 查询,即它既昂贵又烦人。

有什么方法可以在不破坏数据或干扰正在运行的应用程序的情况下解决这个问题?

考虑到你想在它上面运行一个全局应用程序,当涉及到字符设置时,MySQL 的适当设置是什么,我在哪里设置它以便它不仅坚持会话而且永远坚持(我猜在我的.cnf)。

谢谢。

编辑

从 export.sql 文件的开头添加值。 我使用以下行导出

mysqldump --opt --u root -pPassword dbName | gzip > database.sql.gz

-- 服务器版本 5.6.21-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

/*!40101 SET NAMES utf8 */;

/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;

/*!40103 SET TIME_ZONE='+00:00' */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;

/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `so_and_so_blabla`
...

编辑 2

从 SELECT col, hex(col) FROM table 添加输出。 请注意,这在原始数据库和导出中都可以正常工作,因为我在导入数据的数据库中使用 SET NAMES latin1 在发出查询之前。

Europas Länder    4575726F706173204CC383C2A46E646572

【问题讨论】:

    标签: mysql utf-8 character-encoding mysqldump


    【解决方案1】:

    只需要担心SET NAMES 更改的三个。

    中文有几个字符需要utf8mb4。

    请记住,client 中的编码是 SET NAMES 所说的。对于中文,我推荐

    • SET NAMES utf8mb4(或同等学历),以及
    • CHARACTER SET utf8mb4 在任何包含中文的列(或从表定义中默认)上,并且
    • 在网页上——注意,不是 utf8mb4。

    编辑

    让我们看看您用于导出和导入的步骤。如果涉及 mysqldump,请查看它生成的文件以查看是否有任何 SET 命令。

    编辑 2

    由于您的 ä 在十六进制中看起来像 C383 C2A4,因此您具有“双重编码”。这可能是由于

    • 将字节编码为 utf8(十六进制 C3A4 代表 ä)插入表中,并且
    • INSERT 期间使用SET NAMES latin1(可能是默认情况下)(不好,因为它与编码不一致),并且
    • 将表中的列声明为CHARACTER SET utf8(好)

    发生的情况是 C3A4 被声明为 latin1 被转换为 C383C2A4 以存储到 utf8 表列中。

    当拉回此类时,第一次解码将为您提供ä,第二次解码将返回所需的ä

    更多关于“双重编码”的讨论,以及如何处理它,见 my character set blog。有 4 种方法可以修复表中的数据。请与他们进行试验,看看哪个最适合您。并使用HEX(col) 来验证表格中的内容。

    【讨论】:

    • 感谢您的回答。试图确切地了解您的意思。在您的回答中,您从“否”开始。你对什么回答“不”?我的主要问题是如何将数据移动到允许我跳过“latin1”的“设置名称”初始查询的数据库中,以便在导出/导入后让事情正常工作。
    • 对不起“不”;我删除了它。并要求提供更多信息。
    • 向问题添加了信息。请查看 EDIT 下的所有内容如您所见,尽管服务器设置为 latin1(尽管所有表都在 utf8 中),但它使用 SET NAMES utf8。
    • /*!40101 SET NAMES utf8 */; 将执行 SET NAMES(假设您运行的版本 >= 4.1.1)。 my.cnf 中的条目是个好主意。注意:如果以 root 身份连接,init_connect 将被忽略。
    • 对我来说仍然很奇怪,在我将它导入到具有 utf8 作为所有character_set_* 值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 2015-05-19
    • 2020-05-09
    • 2012-06-26
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多