mysqli_connect()报错“Unknown charset: utf8mb4”主因是客户端库不支持该字符集,应改用'utf8'或省略$charset参数;PDO需DSN含;charset=utf8mb4并显式建库声明字符集;权限、SQL语法及my.cnf配置不一致亦常见。

PHP mysqli_connect() 报错 Unknown charset: utf8mb4
这是 PHP 7.4+ 连接 MySQL 时的典型报错,根本原因不是字符集本身有问题,而是 mysqli_connect() 的第 5 个参数($charset)传了不被当前 MySQL 客户端库识别的值。比如你写了 'utf8mb4',但底层 libmysqlclient 版本太老,或 PHP 编译时没启用对应支持。
- 确认 MySQL 服务端实际支持的字符集:登录 MySQL 执行
SHOW VARIABLES LIKE 'character_set%';,重点看character_set_client和character_set_server - 不要硬写
'utf8mb4'—— 改用'utf8'(MySQL 中的utf8实际是utf8mb3,兼容性更好);或者干脆省略该参数,让连接自动协商 - 如果必须用
utf8mb4,请确保 PHP 是用 MySQLi 扩展编译时链接了较新版本的 mysqlclient(≥ 5.5.3),且 MySQL 服务端已开启innodb_large_prefix=ON等配套配置
使用 PDO 创建数据库时指定 charset 失败
PDO 的 charset 不是靠 DSN 里的 charset=utf8mb4 单独生效的,它依赖底层驱动是否真正执行了 SET NAMES 或等效初始化。常见失败场景是 DSN 写对了,但连接后立刻建库,而建库语句没继承字符集上下文。
- DNS 中必须显式包含
;charset=utf8mb4,例如:mysql:host=localhost;dbname=test;charset=utf8mb4 - 创建数据库前,先执行一次
SET NAMES utf8mb4(用$pdo->exec('SET NAMES utf8mb4')) - 建库 SQL 必须显式声明字符集:
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,不能只靠连接默认值 - 检查
pdo_mysql.default_socket是否指向正确 socket 路径,错误路径会导致连接降级为 TCP,有时触发字符集协商异常
phpMyAdmin 或脚本里 CREATE DATABASE 报错 “Unknown character set”
这个报错往往不是 PHP 层面的问题,而是 MySQL 用户权限不足或 SQL 模式限制。比如用户只有 SELECT 权限,却尝试执行 CREATE DATABASE;或者 MySQL 启用了严格模式 + NO_ENGINE_SUBSTITUTION,而建库语句里漏写了 CHARACTER SET 子句。
- 确认当前 MySQL 用户有
CREATE权限:SHOW GRANTS FOR 'user'@'host'; - 建库语句必须完整,尤其是字符集和排序规则:
CREATE DATABASE `mydb` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 避免在 SQL 中混用反引号和单引号——
CHARACTER SET 'utf8mb4'是错的,应为CHARACTER SET utf8mb4(无引号) - 如果用的是低版本 MySQL(utf8mb4 根本不被识别,只能退回到
utf8(即 utf8mb3)
mysqli_set_charset() 返回 false 却不报错
这个函数静默失败非常隐蔽。它只在连接建立后才有效,如果在 mysqli_connect() 返回 false 后还调用它,或者连接已被关闭,都会返回 false 且不抛异常。
立即学习“PHP免费学习笔记(深入)”;
- 务必检查
mysqli_connect()返回值是否为对象,再调用mysqli_set_charset($conn, 'utf8mb4') - 优先用面向对象写法:
$mysqli->set_charset('utf8mb4'),它比过程式更易捕获状态 - 如果返回 false,立即查
mysqli_connect_error()或$mysqli->connect_error,而不是假设是字符集问题 - 注意:该函数设置的是客户端连接层的字符集,不影响数据库/表/列本身的定义,建库建表仍需显式声明
my.cnf)里的 [client] 和 [mysqld] 段落字符集设置不一致,会导致客户端连上后默认字符集与服务端不匹配,后续任何 PHP 层面的 set_charset 都只是“打补丁”,治标不治本。











