当前位置:首页 >  站长 >  数据库 >  正文

用户昵称带个表情就存不进去?MySQL utf8 转 utf8mb4 完整迁移方案

 2026-08-28 15:00  来源: 互联网   我来投稿 撤稿纠错

  一键部署OpenClaw

用户注册昵称是表情符,提交后昵称变成空白,或者干脆报错 Incorrect string value。这是 MySQL 老 utf8 的锅:它的 utf8 实现最多三个字节,而 emoji 和部分生僻字是四字节字符,塞不进去。真正的完整 UTF-8 在 MySQL 里叫 utf8mb4,mb4 就是 most bytes 4。

迁移分四层:库默认字符集、表字符集、列字符集、连接字符集,全都要改,漏一层就会出现「表是 utf8mb4 但还是存不进」的诡异现象。先摸清现状:

-- 看库里各表的字符集

SELECT TABLE_NAME, TABLE_COLLATION

FROM information_schema.TABLES

WHERE TABLE_SCHEMA = 'site_db';

-- 看连接字符集

SHOW VARIABLES LIKE 'character_set%';

逐表转换用 CONVERT TO,它会连表带全部列一起改:

ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

ALTER TABLE posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- 库的默认值(只影响新建表)

ALTER DATABASE site_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

注意两点:一是整库所有表要用同一个 collation,混用 utf8_general_ci 和 utf8mb4_general_ci 的表做 JOIN 时索引会失效,性能直接跳水;二是大表 CONVERT 会锁表重建,几百万行的表要选低峰期,或者用 pt-online-schema-change 在线改。

最后是连接层,三个地方要同步改。PHP 连接:

// PDO 写法

new PDO('mysql:host=localhost;dbname=site_db;charset=utf8mb4', 'user', 'pass');

// 老代码用 SET NAMES 的,改成

$pdo->exec("SET NAMES utf8mb4");

# php.ini 或 my.cnf

; php.ini

pdo_mysql.default_charset = utf8mb4

# my.cnf [mysqld]

character-set-server = utf8mb4

collation-server = utf8mb4_general_ci

改完拿一个 emoji 实测:插入、查询、页面显示一条龙走一遍。顺手提醒,迁移前务必先备份,字符集转换是不可逆操作,中间断了或者 collation 选错,恢复起来非常痛苦。

数据来源:MySQL官方手册 

申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!

相关标签
php教程
mysql

相关文章

  • 手滑 DELETE 忘了 WHERE?binlog 十分钟找回误删数据

    DBA圈流传一句话:没删过库的人生不完整。但删了能找回来,才是真本事。误删数据的救命稻草就是binlog——它记录了每一行数据的变更,既能用来恢复,也能反查哪条语句闯的祸。前提是提前开了log-bin,没开的话神仙难救,所以第一件事去检查配置。SHOWVARIABLESLIKE'log_bin';-

  • 数据库备份脚本只会 dump 一把梭?这份定时备份方案能救命

    问过不少站长:有备份吗?答有,拷过一份。再问什么时候拷的?去年。这种备份等于没有。数据库备份要做到三条:自动化、异地存、定期演练恢复。三条都不难,一个脚本加一条cron全搞定。先说dump命令怎么写才对。默认参数导出的文件恢复时容易出问题,这几个参数建议照抄:mysqldump-uroot-p'密码

    标签:
    mysql
    数据库
  • 一台数据库扛不住了?MySQL 主从复制搭建实录,附跳坑指南

    站点流量上来后,读写全压在一台MySQL上,页面越来越慢,更闹心的是没备份没冗余,机器一挂全站完蛋。主从复制是数据库水平扩展的第一步:主库写、从库读,顺便从库就是一台热备。原理不难,就是主库把变更写进binlog,从库拉回来重放。第一步,主库开binlog并建复制账号:#主库my.cnf[mysql

    标签:
    mysql
  • 页面白屏不报错?把 PHP 的错误日志配明白,排错效率翻倍

    线上环境出于安全把错误显示关了,这是对的——报错信息暴露路径给攻击者等于送情报。但代价是出了问题页面上啥都没有,只剩白屏。正确姿势是:页面上不显示,错误全部落日志。;php.ini生产环境错误处理四件套display_errors=Off;页面不显示错误log_errors=On;错误写日志erro

    标签:
    php教程
  • 定时任务还在页面里套 include?cron + PHP CLI 才是正路

    见过不少老站的处理方式:写个task.php,靠别人挂个监控或者用JS定时刷来触发,更狠的是每次有人访问首页顺带跑一遍统计。这些歪招的共同问题是不可控——没人访问就不跑,被搜索引擎高频抓取就狂跑。定时任务就该交给系统的cron。PHP从命令行跑有个专属的SAPI叫CLI,和网页那套php-fpm是两

    标签:
    php教程

热门排行

信息推荐