MySQL中文及emoji乱码须库、表、连接三者统一为utf8mb4:宝塔默认latin1/utf8mb3不支持,仅改库或表无效;需ALTER DATABASE和CONVERT TO utf8mb4,并在PHP连接时显式设charset=utf8mb4,同时配置my.cnf的character-set-server与init_connect。

数据库乱码不是“网页没设 charset”导致的,而是 MySQL 底层存不进完整中文和 emoji —— 必须把库、表、连接三者字符集统一为 utf8mb4,缺一不可。
为什么只改数据库或只改表还是乱码
宝塔新建库默认用 latin1 或 utf8(实为 utf8mb3),这两种编码都不支持 emoji 和部分生僻汉字。即使你手动把表改成 utf8mb4,但库仍是 latin1,新创建的字段、索引、临时表仍按库默认走,结果还是乱码。
- 执行
ALTER DATABASE `your_db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;是第一步 - 再对每张表执行
ALTER TABLE `table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 注意:不能只用
MODIFY或CHANGE改单个字段,那样只改列定义,不转已有数据 - 如果表里已有乱码数据(比如显示为问号),
CONVERT TO也无法恢复,只能从备份还原
PHP 连接时没指定 utf8mb4,查出来照样是乱码
MySQL 客户端连接默认走服务器配置,而宝塔装的 MySQL 往往没配好 init_connect,导致 PHP 即使用 mysqli 或 PDO 连上,实际连接层仍按 latin1 解析字段值。
-
mysqli方式:连接后立刻调用$mysqli->set_charset("utf8mb4"),别信 DSN 里的charset=utf8,那是旧版写法,无效 -
PDO方式:DSN 中必须显式加;charset=utf8mb4,例如mysql:host=localhost;dbname=test;charset=utf8mb4 - 检查是否生效:在 PHP 里执行
SELECT CHARSET(), COLLATION(),返回应为utf8mb4和utf8mb4_unicode_ci - 别被
phpinfo()里的default_charset欺骗——它只影响 HTTP header,跟 MySQL 连接无关
MySQL 配置文件没同步,重启后又退回 latin1
宝塔面板修改数据库配置后,如果不改 MySQL 主配置文件,服务重启就会恢复默认行为,新创建的库/表又会掉回 latin1。
- 编辑
/etc/my.cnf或/www/server/mysql/etc/my.cnf,在[mysqld]段下添加: character-set-server=utf8mb4collation-server=utf8mb4_unicode_ciinit_connect='SET NAMES utf8mb4'- 删掉已有的
skip-character-set-client-handshake行(如果有) - 改完执行
service mysqld restart或bt 16重启数据库
容易被忽略的校对规则细节
utf8mb4_unicode_ci 和 utf8mb4_general_ci 都能存 emoji,但后者在 5.7+ 已被标记为 deprecated;utf8mb4_0900_as_cs 是 MySQL 8.0 默认,区分大小写且更准,但宝塔兼容性一般,首次迁移建议用 utf8mb4_unicode_ci。
- 建库语句里不写
COLLATE,MySQL 会按collation-server落,默认可能是utf8mb4_0900_as_cs,导致旧程序排序异常 - phpMyAdmin 或宝塔「管理」页执行 SQL 时,当前连接的 collation 可能和表不一致,务必在语句开头加
SET NAMES utf8mb4; - 如果用 Laravel、ThinkPHP 等框架,还要确认其数据库配置中
charset和collation项也设为utf8mb4和utf8mb4_unicode_ci











