如何在my.cnf中将MySQL默认字符集更改为UTF-8?

365

我们目前在PHP中使用以下命令来设置应用程序的字符集为UTF-8

由于这会增加一些额外工作量,我们希望将其设置为MySQL的默认设置。我们可以在/etc/my.cnf或其他位置进行设置吗?

SET NAMES 'utf8'
SET CHARACTER SET utf8

我查看了 /etc/my.cnf 文件,但是没有找到有关字符集的默认设置。

于是我执行以下操作将 MySQL 的字符集和校对规则变量设置为 UTF-8:

skip-character-set-client-handshake
character_set_client=utf8
character_set_server=utf8

这是处理此问题的正确方式吗?


24
请注意,更好的默认值应该是 utf8mb4,即具有完全 Unicode 支持的真正 UTF-8。请参阅如何在 MySQL 数据库中支持完整的 Unicode - Mathias Bynens
1
@Jorre,您是否反对将其更改为“utf8mb4”?目前它所处的情况可能会产生一种危险的先例。 - Evan Carroll
19个回答

481

要将默认编码设置为UTF-8,您需要将以下内容添加到my.cnf/my.ini中:

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4


[mysqld]
collation-server = utf8mb4_unicode_520_ci
init-connect='SET NAMES utf8mb4'
character-set-server = utf8mb4

如果您想更改现有数据库的字符集,请告诉我...因为您的问题没有直接指明,所以我不确定这是否是您想要做的。

编辑:由于utf8只是UTF-8的子集,MySQL和MariaDB都将UTF-8称为utf8mb4,因此我在原来的答案中用utf8mb4替换了utf8


20
上述的my.cnf设置对我也起作用了。此外,我还必须确保表格被正确设置,例如 ALTER TABLE Table CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci; - Chris Livdahl
9
不适用于mysql 5.5。 我使用的是:<br/> [mysqld]

utf-8更改

collation-server = utf8mb4_unicode_ci init-connect='SET NAMES utf8mb4' character-set-server = utf8mb4 其他地方也要使用utf8mb4,如上所述。
- Champ
12
在Ubuntu 12.04上,我使用以下方法使其工作——如果我删除了[mysqld]之后的第一行。 - Brandon Bertelsen
4
似乎在[mysqld]部分不再允许使用default-character-set。 - marsbard
5
请注意,如果您需要使用UTF-8,请勿使用MySQL的utf8字符集。请改用utf8mb4代替,以便支持所有Unicode字符。 - Mathias Bynens
显示剩余7条评论

263

对于最近版本的MySQL,

default-character-set = utf8

这可能会引起问题。我认为它已经被弃用了。

正如Justin Ball在《升级到MySQL 5.5.12版本后,MySQL无法启动》中所说,您应该:

  1. 删除该指令,然后一切都将正常。

  2. 那么您的配置文件(例如'/etc/my.cnf')应该是这样的:

[mysqld]
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
  • 重新启动MySQL。

  • 为确保你的MySQL使用UTF-8编码,请在MySQL提示符下运行以下查询:

    • 第一个查询:

       mysql> show variables like 'char%';
      

      输出应如下所示:

       +--------------------------+---------------------------------+
       | Variable_name            | Value                           |
       +--------------------------+---------------------------------+
       | character_set_client     | utf8                            |
       | character_set_connection | utf8                            |
       | character_set_database   | utf8                            |
       | character_set_filesystem | binary                          |
       | character_set_results    | utf8                            |
       | character_set_server     | utf8                            |
       | character_set_system     | utf8                            |
       | character_sets_dir       | /usr/local/mysql/share/charsets/|
       +--------------------------+---------------------------------+
      
    • 第二个查询:

       mysql> show variables like 'collation%';
      

      查询结果是:

       +----------------------+-----------------+
       | Variable_name        | Value           |
       +----------------------+-----------------+
       | collation_connection | utf8_general_ci |
       | collation_database   | utf8_unicode_ci |
       | collation_server     | utf8_unicode_ci |
       +----------------------+-----------------+
      

  • 你的第一行 max_allowed_packet=64M 是否与这个 UTF8 问题有关? - malhal
    1
    在MariaDB v5.5上尝试过,可以工作,谢谢!mysql Ver 15.1 Distrib 5.5.35-MariaDB,for debian-linux-gnu(x86_64)using readline 5.1 - cenk
    我认为您不需要删除default-character-set,而是可以改为loose-default-character-set = utf8-即在前面加上“loose-”。这会使mysqlbinlog很高兴,如果您需要使用它-请搜索:*"loose-default-character-set" mysqlbinlog*。 - KajMagnus
    我需要使用skip-character-set-client-handshake,否则一些变量仍然没有改变。 - cn123h
    由于缺乏对许多广泛使用的字符的支持,以及不支持字符可能带来的高风险(数据截断、查询失败),大多数人都会选择使用 utf8mb4 而不是 utf8,并使用相应的排序规则 utf8mb4_unicode_ci 或类似的规则。 - cazort
    显示剩余3条评论

    64

    这个问题已经有很多答案了,但Mathias Bynens提到应该使用'utf8mb4'而不是'utf8'以获得更好的UTF-8支持('utf8'不支持4字节字符,字段在插入时被截断)。我认为这是一个重要的区别。因此,这里又有一个关于如何设置默认字符集和排序规则的答案,它将允许您插入一堆💩。

    这适用于MySQL 5.5.35。

    请注意,某些设置可能是可选的。由于我不确定是否忘记了什么,所以我会将这个答案设为社区wiki。

    旧设置

    mysql> SHOW VARIABLES LIKE 'char%'; SHOW VARIABLES LIKE 'collation%';
    +--------------------------+----------------------------+
    | 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/ |
    +--------------------------+----------------------------+
    8 rows in set (0.00 sec)
    
    +----------------------+-------------------+
    | Variable_name        | Value             |
    +----------------------+-------------------+
    | collation_connection | utf8_general_ci   |
    | collation_database   | latin1_swedish_ci |
    | collation_server     | latin1_swedish_ci |
    +----------------------+-------------------+
    3 rows in set (0.00 sec)
    

    配置

    #  
    # UTF-8 should be used instead of Latin1. Obviously.
    # NOTE "utf8" in MySQL is NOT full UTF-8: http://mathiasbynens.be/notes/mysql-utf8mb4
    
    [client]
    default-character-set = utf8mb4
    
    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    
    [mysql]
    default-character-set = utf8mb4
    

    新设置

    mysql> SHOW VARIABLES LIKE 'char%'; SHOW VARIABLES LIKE 'collation%';
    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8mb4                    |
    | character_set_connection | utf8mb4                    |
    | character_set_database   | utf8mb4                    |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8mb4                    |
    | character_set_server     | utf8mb4                    |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    8 rows in set (0.00 sec)
    
    +----------------------+--------------------+
    | Variable_name        | Value              |
    +----------------------+--------------------+
    | collation_connection | utf8mb4_general_ci |
    | collation_database   | utf8mb4_unicode_ci |
    | collation_server     | utf8mb4_unicode_ci |
    +----------------------+--------------------+
    3 rows in set (0.00 sec)
    

    character_set_system 始终为utf8

    这不会影响现有的表格,仅是默认设置(用于新表格)。 可以使用以下ALTER代码来转换现有表格(无需进行倾卸 - 恢复操作):

    ALTER DATABASE databasename CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    

    编辑:

    在MySQL 5.0服务器上:character_set_client,character_set_connection,character_set_results,collation_connection仍保持为latin1。发出SET NAMES utf8命令(utf8mb4在该版本中不可用)也会将它们设置为utf8。


    注意: 如果您有一个utf8表,其中包含类型为VARCHAR(255)的索引列,则在某些情况下无法转换,因为超过了最大键长度(指定的键太长;最大键长度为767个字节)。如果可能,请将列大小从255减小到191(因为191 * 4 = 764 < 767 < 192 * 4 = 768)。之后,可以转换表格。


    我按照您的设置进行了操作,但是我发现character_set_database仍然是utf8,而collation_databaseutf8_bin。我有遗漏什么吗? - Stewart
    找到了我错过的东西。这两个设置是在创建数据库本身时设置的。请参见此问题;https://dev59.com/RGEh5IYBdhLWcg3wTB72 - Stewart
    1
    在 [mysqld] 部分中添加 character-set-client-handshake = FALSE,这样即使在应用层犯错误,它也会始终使用默认编码。 - Lukas Liesis
    嗨,我已经尝试了这个解决方案,但仍然无法显示 character_set_client | utf8mb4。它是utf8。只有 character_set_database utf8mb4 和 character_set_server utf8mb4 是 utf8mb4,其他没有改变。请帮助我。 - Bhavin Chauhan
    @baic6 我建议添加一条说明,澄清为什么只有索引列才会导致问题。767字节的限制仅适用于索引列,因为“键”的限制。对于非索引列,通常不适用此限制。如果某个列的值具有最大字节长度,例如255个字符,并且使用了最大的3个字节的utf8,则仍然只需要255*3个字节,在这种情况下,utf8mb4仅使用3个字节,因为utf8mb4中的这些字符也仅需要3个字节。也就是说,除非将不适合utf8的字符存储到列中,否则信息已经丢失。 - sam

    55

    在MySQL 5.5中,我的my.cnf文件中有以下内容:

    [mysqld] 
    init_connect='SET collation_connection = utf8_unicode_ci' 
    init_connect='SET NAMES utf8' 
    character-set-server=utf8 
    collation-server=utf8_unicode_ci 
    skip-character-set-client-handshake
    

    结果是

    mysql> show variables like "%character%";show variables like "%collation%";
    
    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8                       |
    | character_set_connection | utf8                       |
    | character_set_database   | utf8                       |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8                       |
    | character_set_server     | utf8                       |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    8 rows in set (0.00 sec)
    
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_unicode_ci |
    | collation_database   | utf8_unicode_ci |
    | collation_server     | utf8_unicode_ci |
    +----------------------+-----------------+
    3 rows in set (0.00 sec)
    

    2
    skip-character-set-client-handshake 究竟是什么,以及在什么情况下需要使用它? - Simon East
    3
    当使用 show variables like "%collation%"; 命令时,我发现 'collation_connection' 显示为 utf8_general_ci,而 collation_database 和 collation_server 则显示为 utf8_unicode_ci。加入 skip-character-set-client-handshake 这行代码后,通用条目变成了 Unicode 格式,所以三者保持了一致性。 - Vaughany
    2
    在MySQL 5.6上,skip-character-set-client-handshake并不像@Vaughany所说的那样工作。有什么建议吗? - Ababneh A
    4
    skip-character-set-client-handshake对我起了作用(当然还有"character-set-server"和"collation-server"——在Debian 7上)。 init_connect使用或不使用skip都没有区别,似乎是多余的。+1谢谢。 - Jeff
    3
    skip-character-set-client-handshake忽略客户端发送的字符集信息。它可以用于在通信过程中强制使用特定的字符集,但如果客户端期望其他字符集,可能会导致问题。我建议您最好在客户端(应用程序)上指定字符集。 - 0b10011
    显示剩余2条评论

    35
    注意:my.cnf 文件位于 /etc/mysql/
    在添加了这些行之后:
    [mysqld]
    collation-server = utf8_unicode_ci
    init-connect='SET NAMES utf8'
    character-set-server = utf8
    skip-character-set-client-handshake
    
    [client]
    default-character-set   = utf8
    
    [mysql]
    default-character-set   = utf8
    
    请确认重启服务器:

    不要忘记重新启动服务器:

    sudo service mysql restart
    

    2
    注意:这会更改默认设置;它不会更改任何现有列的编码。 - Rick James

    28

    MySQL v5.5.3及以上版本:

    仅需在[mysqld]部分添加三行内容:

    [mysqld]
    character-set-server = utf8
    collation-server = utf8_unicode_ci
    skip-character-set-client-handshake
    

    注意:在这里包含skip-character-set-client-handshake可以避免在[mysqld]中同时包含init-connect和在[client]以及[mysql]部分中包含default-character-set的需要。


    2
    哇,这个问题有很多重复的答案,但是这似乎是最简单的一个。在v5.5.44上也适用于我。 - Justin Watt

    24

    NijaCat的答案已经很接近了,但是有些过于详细:

    要将默认编码设置为UTF-8,你需要在my.cnf中添加以下内容。

    [client]
    default-character-set=utf8
    
    [mysqld]
    default-character-set = utf8
    

    然后,进行验证:

    mysql> show variables like "%character%";show variables like "%collation%";
    
    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8                       |
    | character_set_connection | utf8                       |
    | character_set_database   | utf8                       |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8                       |
    | character_set_server     | utf8                       |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    8 rows in set (0.00 sec)
    
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_general_ci |
    | collation_database   | utf8_general_ci |
    | collation_server     | utf8_general_ci |
    +----------------------+-----------------+
    3 rows in set (0.00 sec)
    

    5
    好的回答。也许对哪些部分是过度配置的简要说明会帮助人们决定他们想在其配置中使用什么。 - Mike Samuel
    @Derek,[mysql] default-character-set=utf8 是什么意思? - Pacerier
    2
    [客户端]选项组已经为所有读取my.cnf文件的MySQL客户端设置了选项。[mysql]组仅为“mysql”客户端二进制文件设置选项,特别是。如果您想设置一个不适用于其他客户端的mysql选项,则使用此组是合适的,但在两个位置设置相同的选项值是冗余的。http://dev.mysql.com/doc/refman/5.6/en/option-files.html - Derek
    1
    @Mike Samuel,将默认字符集设置为utf8已经隐含了utf8_general_ci的默认排列方式。另一方面,“init-connect ='SET NAMES utf8'”是一个有点有趣的想法,因为它试图强制所有连接到服务器的客户端使用utf8,但这取决于连接用户的连接权限而应用不一致,我怀疑一些连接的第三方客户端可能会感到困惑,当服务器覆盖他们请求的字符集时。http://dev.mysql.com/doc/refman/5.6/en/charset-applications.html - Derek
    1
    [mysqld]中使用character-set-server而不是default-character-set - Rick James
    如果你遇到了 unknown variable 'default-character-set=utf8' 的错误,请查看这个链接:https://dev59.com/s2sz5IYBdhLWcg3wsaAN#12409934 - NeverEndingQueue

    23

    我还发现,在 [mysqld] 标题下设置 default-character-set = utf8 后,MySQL 5.5.x 在 Ubuntu 12.04(Precise Pangolin)下无法启动。


    16
    这是一个MySQL的bug编号为#52047。在[mysqld]下,应该使用character-set-server而不是default-character-set。(非常令人困惑,我同意!) - Mathias Bynens
    是的。在5.0中已被弃用;在5.5中已被移除。 - Rick James

    11

    这里列出的所有设置都是正确的,但以下是最优和足够的解决方案:

    [mysqld]
    init_connect='SET collation_connection = utf8_unicode_ci'
    character-set-server = utf8
    collation-server = utf8_unicode_ci
    
    [client]
    default-character-set = utf8
    

    将这些内容添加到/etc/mysql/my.cnf中。

    请注意,我选择使用utf8_unicode_ci排序规则类型是因为性能问题。

    结果如下:

    mysql> SHOW VARIABLES LIKE 'character%';
    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8                       |
    | character_set_connection | utf8                       |
    | character_set_database   | utf8                       |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8                       |
    | character_set_server     | utf8                       |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    
    mysql> SHOW VARIABLES LIKE 'collation%';
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_unicode_ci |
    | collation_database   | utf8_unicode_ci |
    | collation_server     | utf8_unicode_ci |
    +----------------------+-----------------+
    

    这是当您以非超级用户身份连接时的情况!

    例如,在使用utf8_unicode_ci排序规则时,作为SUPER和非SUPER用户的连接区别如下:

    拥有SUPER权限的用户:

    mysql> SHOW VARIABLES LIKE 'collation%';
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_general_ci | <---
    | collation_database   | utf8_unicode_ci |
    | collation_server     | utf8_unicode_ci |
    +----------------------+-----------------+
    

    用户拥有非SUPER权限:

    mysql> SHOW VARIABLES LIKE 'collation%';
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_unicode_ci |
    | collation_database   | utf8_unicode_ci |
    | collation_server     | utf8_unicode_ci |
    +----------------------+-----------------+
    

    我写了一篇全面的文章(俄文),详细解释为什么您应该使用这两个选项之一。考虑了所有类型的字符集校对规则:服务器、数据库、连接、表甚至列。

    我希望这篇文章能够帮助澄清不清楚的方面。


    3
    我希望您能提供英文版,因为我无法阅读俄语,并且Google翻译对于技术性文本并不是很有帮助。但从我所了解的情况来看,这篇文章应该非常有趣。谢谢您考虑我的请求! - Martijn Heemels
    2
    你能解释一下是哪个设置未能设置超级用户连接排序规则吗?(是否有解决方案) - KCD
    @gahcep,您提到由于性能问题使用了utf8_unicode_ci,那么为什么不使用utf8_bin呢? - Pacerier
    嗨,Paceriar。说得好。现在我不确定使用 utf8_unicode_ci 是否正确。从未花时间测试过性能。 - Sergei Danielian

    9
    在Xubuntu 12.04下,我只需添加以下内容:
    [mysqld]
    character_set_server = utf8
    

    转到 /etc/mysql/my.cnf

    结果如下

    mysql> show variables like "%character%";show variables like "%collation%";
    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8                       |
    | character_set_connection | utf8                       |
    | character_set_database   | utf8                       |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8                       |
    | character_set_server     | utf8                       |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    8 rows in set (0.00 sec)
    
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_general_ci |
    | collation_database   | utf8_general_ci |
    | collation_server     | utf8_general_ci |
    +----------------------+-----------------+
    3 rows in set (0.00 sec)
    

    此外,请参阅 http://dev.mysql.com/doc/refman/5.6/en/charset-server.html 了解更多信息。这个链接会对你有所帮助。

    你还需要添加[client]default-character-set=utf8,否则当你在命令行使用mysql时,它可能不会使用utf8,从而破坏任何备份你导出到文件中的数据。 - malhal

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接