提起 MySQL 的安装与卸载,很多人第一反应就是“下一步下一步装完就收工”。但我在一线折腾数据库的时间长了,见过太多在安装阶段就卡住、在卸载阶段又留一屁股后患的场面:装完服务起不来,root 密码设了三四次都进不去,3306 端口老是被莫名其妙的东西占住;最头疼的是旧版本没卸干净就装新版本,残留的服务、注册表项和配置文件互相打架,一排查就是半天。这篇东西我想把 MySQL 安装与卸载从头到尾捋一遍:版本怎么选,Windows、Linux、Docker 下常见的安装方式怎么做,装完之后初始化、密码、远程访问有哪些绕不开的步骤,以及卸载时哪些残留必须清理,最后是高频报错的排查思路。无论你是刚开始学数据库的学生,还是要在服务器上部署生产环境的人,都能在里面找到可以直接抄作业的部分。
1. 动手之前:先搞清楚需求和版本
1.1 版本选型:8.x 还是 5.7,社区版还是企业版
很多人上来就下载最新版,但其实选版本本身就是第一个坑。MySQL 8.0 已经发布多年,8.4 LTS 也已经进入维护周期;而 5.7 处于维护模式,如果没有特别的历史包袱,新项目不建议再选 5.7,直接上 8.x 更省心。8.x 带来了不少实际用得上东西,比如窗口函数、公共表表达式、不可见索引,还有默认的 caching_sha2_password 认证插件。
认证插件这件事得单独拎出来说一下。MySQL 5.7 默认用的是 mysql_native_password,8.x 默认是 caching_sha2_password。前者是很多老客户端、老驱动能直接连的,后者安全性更高,但如果你用的是很老的应用框架或连接工具,就会出现“密码明明对,就是连不上”的尴尬。所以版本选择不光是看新功能,还要看你的客户端驱动能不能跟上。
给一个相对稳的选型逻辑:
- 学习、新项目、新环境:选最新稳定版 MySQL 8.x(或 8.4 LTS),不要选老版本,除非你明确知道为什么要选它。
- 老项目升级、兼容老驱动:如果必须用 5.7,尽量控制版本在最后一版,同时早做迁移计划。
- 生产环境:跟着团队的运维规范走,或者选用发行版官方的 MySQL RPM/DEB 包,配合 LTS 版本,避免频繁升级。
社区版和企业版的差别,对绝大多数开发者来说可以忽略。社区版功能已经覆盖了日常开发、测试、中小规模生产环境;企业版主要是多了在线备份、监控、技术支撑这类商业化能力,个人使用和学习完全不用考虑。
1.2 安装前的环境检查:查残留、查端口、查依赖
我每次安装之前都会先花几分钟做一个环境清单检查,这一步能避免掉后面一半以上的问题。首先是看系统里有没有装过 MySQL 或者 MariaDB。判断一条命令就够了:
mysql --version where mysql # Windows 专用:查找 mysql.exe 所在路径 which mysql # Linux/macOS 专用:查看 mysql 命令路径如果命令不存在,说明大概率没装过,但也不排除只装了客户端没装服务端,或者安装残留把命令弄丢了。接着查 3306 端口是否被占用:
# Windows netstat -ano | findstr 3306 # Linux ss -lntp | grep 3306端口被占用是安装完成后启动失败的高频原因。常见占用方包括另一个 MySQL 实例、MariaDB、或者某些开发套件自带的数据库组件。如果发现有程序占着 3306,要么先停掉它,要么干脆换一个端口,别硬扛。
Linux 上还有一个容易被忽略的点是依赖库。MySQL 8.x 的 rpm 包依赖 libaio 等基础库,用 yum 或 dnf 装官方 rpm 时一般会自动处理,但如果你用 tar.gz 方式解压安装,就很可能因为缺库导致 mysqld 启动时报错。Debian/Ubuntu 上如果缺少 ncurses、libaio,通常 apt 也会自动带,但最好提前确认一下系统包管理器状态正常。另外,确保你有足够的磁盘空间,5~10GB 看似已经很宽裕,但如果你计划导入几个大库,建议提前留出数据文件两倍以上的空间。
在 Windows 上安装时还要注意安装路径。别把 MySQL 解压到带中文、带空格、或者权限控制很复杂的目录下。解压到D:\tools\MySQL\这类纯英文路径是最省心的。路径里有中文,后续配置 my.ini 和注册服务时经常会出现莫名其妙的字符集或转义问题。
2. 三种主流安装方式,总有一种适合你
2.1 Windows 下的 MSI 安装与 ZIP 免安装
Windows 上最常见的两种方式:MSI 图形化安装包和 ZIP 免安装压缩包。对新手来说 MSI 最友好,对需要精细控制安装内容的场景来说 ZIP 更灵活。
MSI 安装不需要太动脑,下载 mysql-installer-community 安装包后一路按向导走。需要留意的点:
- 组件选择建议选 Server Only,避免装一堆用不到的组件。
- 安装类型通常选单机版 Standalone MySQL Server。
- 配置页面会让你设置 root 密码,这一步必须认真设置。
- Windows 服务建议勾选并设置为自动启动,方便后面维护。
MSI 装起来省心,但一旦安装包版本和你机器上已有的组件冲突,残留问题同样会出现。如果你想控制安装的每个细节,我反而更推荐 ZIP 方式。操作步骤如下:
- 去官网下载 zip 压缩包,解压到纯英文路径,比如
D:\mysql-8.4.x。 - 在解压目录下新建一个 my.ini,基础配置可以写成这样:
[mysqld] basedir=D:/mysql-8.4.x datadir=D:/mysql-8.4.x/data port=3306 character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci [client] default-character-set=utf8mb4注意 basedir 和 datadir 的区别。basedir 是程序目录,datadir 是数据文件目录,两个别混。my.ini 的路径分隔符用正斜杠/或双反斜杠\\都可以,但别只写一个反斜杠,否则容易被当成转义符。
- 用管理员权限打开命令行,进入解压目录,执行初始化命令:
mysqld --initialize-insecure这个命令会在 datadir 位置初始化数据目录,并生成一个没有密码的 root 账号。如果你用mysqld --initialize则会生成随机密码并写入日志文件,对新手来说反而不如--initialize-insecure方便,反正后面也要改密码。
- 注册 Windows 服务并启动:
mysqld --install MySQL net start MySQL- 登录:
mysql -u root -p这里密码留空,回车直接进。进去之后第一件事就是把 root 密码改掉,第 3 部分会专门讲。
ZIP 方式最大的坑是收尾工作更繁琐。注册服务后,如果以后卸载,必须先用sc delete MySQL把服务清理掉,只删目录是不彻底的。另外 data 目录不要手动创建,也不要从网上复制别人的 data 目录,必须用mysqld --initialize-insecure自己生成,否则权限和元数据会乱。
2.2 Linux 下用 apt/yum 包管理器安装
Linux 上安装 MySQL 可以走发行版自带的包管理,也可以走官方仓库。我这里以 Debian/Ubuntu 和 CentOS/RHEL 两条线分别说。
Debian/Ubuntu 最简单:
sudo apt update sudo apt install mysql-server -y装完以后服务一般会自动启动,检查一下状态:
systemctl status mysqlUbuntu 上有一个和 CentOS 很不一样的地方:默认的 root 账户本地认证用的是 auth_socket 插件。也就是说,你用 root 和密码登录往往进不去,但用系统管理员身份执行sudo mysql可以直接进。这不是故障,是设计如此。所以第一次进去不要慌,用sudo mysql登录,再把 root 认证改成密码认证,或者直接创建一个自己用的数据库账号都行。
CentOS/RHEL 则要稍微绕一些,因为默认源里yum install mysql-server装的很可能是 MariaDB,并不是 MySQL。如果确实要装官方 MySQL,推荐添加官方 Yum 仓库:
sudo rpm -Uvh https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm sudo yum install mysql-community-server -y注意上面的仓库地址需要按你的系统版本来选,el7、el8、el9 不能混用。
装完启动:
sudo systemctl enable --now mysqldCentOS 安装后会产生一个临时密码,记录在日志里:
sudo grep 'temporary password' /var/log/mysqld.log用这个临时密码登录:
mysql -u root -p登录后会强制要求改密码,先执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';这里注意 MySQL 8.x 对密码复杂度有默认策略,太简单的密码会被直接拒绝。如果只是本地开发环境,你可以后面通过调整 validate_password 组件来放宽限制,但生产环境建议保留强密码策略。
包管理器安装的好处是省心,服务管理、开机自启、依赖处理都帮你弄好了,缺点是可选版本相对固定。如果你要的版本不在仓库里,一般就要走官方仓库或者用 Docker。
2.3 用 Docker 装一个可随时扔掉的 MySQL 环境
如果只是想在本地快速起一个 MySQL 来练手,Docker 是最快的。一条命令就能跑起来:
docker run -d --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0参数的作用分别是:-d后台运行,--name mysql8给容器取名,-p 3306:3306把容器内 3306 映射到宿主机,-e MYSQL_ROOT_PASSWORD指定 root 初始密码。
但这样跑起来的容器有个明显问题:不挂数据卷的话,容器一删数据就没了。所以稍微正经一点的做法是把数据和配置挂出来:
docker run -d --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ -v /data/mysql:/var/lib/mysql \ -v /data/mysql/conf:/etc/mysql/conf.d \ --restart unless-stopped \ mysql:8.0挂载出来的/data/mysql/conf目录可以放自定义的 my.cnf;/data/mysql目录对应数据库文件。这样容器坏了,数据还在宿主机上。
进入容器的命令行:
docker exec -it mysql8 bash mysql -u root -pDocker 方式也有需要注意的地方。首先是权限问题,官方镜像里面的数据目录属于 mysql 用户,如果你把宿主机目录挂载进去,一定要保证宿主机目录权限合适,否则初始化时经常报 Permission denied,常见做法是执行chown -R 999:999 /data/mysql(999 是容器内 mysql 用户的 uid)。其次是端口冲突,宿主机上如果已经有 MySQL 在跑 3306,那映射就得改成-p 3307:3306。我个人建议在生产环境认真评估是否用容器部署 MySQL,毕竟数据库不是无状态服务,网络、存储、备份都要想清楚再上容器。
3. 安装后必须做的三件事:初始化、密码、远程访问
3.1 解压安装场景下的初始化与启动服务
如果你走的是 ZIP 免安装或者 tar.gz 解压安装的路线,初始化这一步最不能省。Windows 上用mysqld --initialize-insecure,Linux 上用mysqld --initialize-insecure --user=mysql,两者含义类似。加--user=mysql的意思是让 mysqld 进程以 mysql 这个系统用户身份去初始化数据目录,避免之后用 root 启动时出现数据目录权限归属混乱。
初始化完成后,Windows 上把 MySQL 注册为系统服务并启动:
mysqld --install MySQL net start MySQLLinux 解压安装则可以直接用:
sudo /usr/local/mysql/bin/mysqld --user=mysql &但更规范的方式是复制官方提供的 systemd 服务文件到 /etc/systemd/system/ 下,再用systemctl start mysql来管理。一开始折腾的时候可能嫌麻烦,但长期维护会发现这条路值得走。
服务起来了,第一步就是登录检查。这时候 root 是没有密码或只有临时密码的。如果你用--initialize初始化的,临时密码会写在日志文件里:
- Windows:数据目录下的 .err 文件,比如
D:\mysql-8.4.x\data\主机名.err。 - Linux(RPM 安装):/var/log/mysqld.log。
- Linux(Debian 安装):/var/log/mysql/error.log。
找到临时密码后登录,执行ALTER USER改成自己的密码,下面展开讲。
3.2 改 root 密码与必做的基础加固
不管用什么方式安装,装完 MySQL 后第一件事绝对是改 root 密码,尤其是初始化时用--initialize-insecure生成空密码的情况,内网环境里空 root 密码比不装还危险。
登录后执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPassword';这个语句会让 root 的密码变更,后面再用mysql -u root -p登录时就需要输入新密码了。注意 8.x 默认有密码校验组件,如果密码长度不够或者太简单会直接报错。自己动手做实验也尽量养成用强密码的习惯。
接下来执行安全加固脚本,Linux 上可以直接跑:
mysql_secure_installation交互式脚本会依次问你要不要删匿名用户、禁不禁止 root 远程登录、要不要删除 test 库、是否立即刷新权限表。对生产环境,我的建议是全部选 Yes,这四条没有一个是不该做的:
- 匿名用户:留着没有任何业务意义,纯属攻击面。
- root 远程登录:生产环境强烈建议禁止。日常运维可以通过堡垒机或本地 Socket 登录,不要把 root 暴露到网络上。
- test 库:默认库对业务无用,留着还容易误写数据。
- 刷新权限:必须做,否则策略只改在了内存里的元数据表上,没有立即生效。
除了脚本提供的加固项,我还会建议创建一个业务专用账号,而不让应用直接连 root:
CREATE USER 'app'@'%' IDENTIFIED BY 'AppPassword123'; GRANT SELECT, INSERT, UPDATE, DELETE ON myappdb.* TO 'app'@'%';为什么要这么做?因为 root 的权限是全库全表的操作,应用账号一旦被拿到就等于拥有了整个数据库。一个应用只需要读自己的库,那就只给这一个库的增删改查权限;将来要加表、调整结构,再单独用 DDL 权限的账号去操作。这套最小权限原则虽然简单,但能拦住很多低级事故。
3.3 开启远程访问:bind-address、授权与防火墙
很多人在本地装好 MySQL,打开数据库管理工具去连却发现连不上。常见原因不外乎这三个:没监听外部地址、没授权远程用户、防火墙没放行。
第一个是 bind-address 配置。MySQL 默认只监听 127.0.0.1,修改配置文件里的:
[mysqld] bind-address = 0.0.0.0改完重启服务。Windows 里是 my.ini,Linux 里是/etc/mysql/mysql.conf.d/mysqld.cnf或/etc/my.cnf,不同发行版路径不一样,可以用grep -r "bind-address" /etc/mysql这样的命令快速定位。
第二个是账号授权。MySQL 的账号是“用户 + 来源主机”组合起来的。想要从任意主机连接,就要建一个'app'@'%'的用户,或者对已有用户做授权:
GRANT ALL PRIVILEGES ON myappdb.* TO 'app'@'%'; FLUSH PRIVILEGES;但这里我建议把 % 换成具体的 IP 或网段,比如'app'@'192.168.1.%',而不是直接把所有来源都放开。生产环境的数据库端口一旦暴露到公网,扫描器几小时就能找上门。
第三个是防火墙。Linux 上用 firewalld 的话:
sudo firewall-cmd --permanent --add-port=3306/tcp sudo firewall-cmd --reloadWindows 上是在“高级安全 Windows Defender 防火墙”里添加入站规则放行 3306 端口,或者第一次启动 MySQL 时允许它通过防火墙。这里要强调一下:端口放行前务必确认数据库本身已经做好了账号密码防护,不然就是裸奔。检查远程是否能连上,在另一台机器执行:
mysql -h 目标IP -P 3306 -u app -p能连上就说明远程访问链路已经打通。
4. 卸载:比安装更容易翻车的环节
4.1 Windows 上彻底卸载 MySQL 的完整步骤
Windows 卸载数据库最怕“卸了但没卸干净”。很多二次安装失败都是因为旧版本残留:服务还在、注册表还有、数据文件没删,结果新版本装到一半就报错。这里给一套完整操作流程。
第一步,停止服务并删除服务。用管理员身份打开命令行:
net stop MySQL sc delete MySQL如果你的服务名不是 MySQL,比如是 MySQL80,就先执行sc queryex type= service state= all | findstr MySQL查看准确名称,再执行sc delete 服务名。
第二步,在“控制面板 -> 程序和功能”里卸载 MySQL 相关组件。如果你用的是 MySQL Installer,也可以重新打开安装器,选择移除所有组件。
第三步,删除残留文件。需要重点检查这几个位置:
C:\Program Files\MySQL(安装目录)C:\ProgramData\MySQL(数据目录和配置文件所在位置,注意 ProgramData 默认是隐藏目录,需要在资源管理器里打开“显示隐藏的项目”)C:\Users\你的用户名\AppData\Roaming\MySQL和C:\Users\你的用户名\AppData\Local\MySQL(缓存和日志)
ProgramData 目录里存放的是 data 目录、my.ini、日志、临时文件,这是卸载清理的重灾区。如果确认数据不再需要,直接整个删除。
第四步,清理注册表。按 Win+R 输入 regedit 打开注册表编辑器,删除如下相关键值:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\MySQLHKEY_LOCAL_MACHINE\SOFTWARE\MySQL
提示:改注册表前记得先备份当前注册表,或者用“文件 -> 导出”把分支导出一个 .reg 文件。注册表删错导致的系统问题比 MySQL 装不上更麻烦。
最后重启一次系统,再检查mysql --version和netstat -ano | findstr 3306,确认命令已经不存在、端口已经空出。整个过程看起来繁琐,但一次做干净,能省掉后面所有“莫名其妙”的问题。
4.2 Linux 下卸载 MySQL 与残留清理
Linux 卸载相对清爽,但还是分发行版来看。
Debian/Ubuntu:
sudo systemctl stop mysql sudo apt purge mysql-server mysql-client mysql-common -y sudo apt autoremove -ypurge 和 remove 的区别是:remove 只删软件包本身,purge 连配置文件一起删。所以我建议用 purge。但即便这样,/var/lib/mysql这个数据目录一般不会被删,需要手动处理:
sudo rm -rf /var/lib/mysql sudo rm -rf /etc/mysql sudo rm -rf /var/log/mysqlCentOS/RHEL:
sudo systemctl stop mysqld sudo yum remove mysql-community-server mysql-community-client mysql-community-libs mysql-community-common -y同样要手动清理:
sudo rm -rf /var/lib/mysql sudo rm -rf /etc/my.cnf /etc/my.cnf.d sudo rm -f /var/log/mysqld.log清完之后用命令复核残留:
rpm -qa | grep mysql dpkg -l | grep mysql如果还有未卸载的包,就逐个rpm -e 包名或者apt purge 包名。另外,有些系统自带的 MariaDB 组件不要误删,除非你确认自己不需要。整体上 Linux 的卸载比 Windows 干净,但数据目录、配置文件、日志这三个位置永远要手动确认。
4.3 Docker 容器卸载与数据卷清理
Docker 卸载 MySQL 更像“销毁容器”,步骤简单,但数据清理往往容易被忽略。先看正在运行的容器:
docker ps -a | grep mysql找到容器 ID 后执行:
docker stop <容器ID> docker rm <容器ID>如果不再需要镜像,可以删掉:
docker rmi mysql:8.0数据卷清理要单独查:
docker volume ls | grep mysql docker volume rm <卷名>如果当初是用-v /data/mysql:/var/lib/mysql这种宿主机目录挂载方式,那数据其实不在 Docker 的数据卷里,而在宿主机/data/mysql。这种情况下要删除数据,得在宿主机上手动删目录。删除前依旧先确认是否有备份需求,数据库数据在某些场景里可能是“删除操作不可原谅”的,所以我在卸载前永远先备份。
5. 高频问题排查:装不上、起不来、连不上
5.1 端口占用:3306 被谁占住了
症状是启动 MySQL 或执行 net start 时报 bind failed,或者连接 MySQL 时提示 Can't connect to MySQL server on '127.0.0.1' (10061)。排查思路很直接:
Windows:
netstat -ano | findstr 3306得到的最后一位是 PID,在任务管理器里根据 PID 找到对应进程。如果占用方是一个老 MySQL 实例,先停掉它;如果是被开发工具自带的数据库占用,也建议先停掉其中一个。
Linux:
ss -lntp | grep 3306如果确实不想停占用程序,也可以把新装的 MySQL 端口改掉。在 my.ini 或 my.cnf 里把 port 改成 3307、3308 等空闲端口。但改端口要记住,改完后所有连接方都得跟着改,包括防火墙规则和数据库连接字符串。
还有一种容易忽略的情况:MySQL 服务配置了 3306,但数据目录里之前的配置残留了 socket 路径或者端口,重启时加载的配置不是你正在编辑的那个文件。排查时可以执行mysqld --verbose --help | grep my.cnf查看实际读取的配置文件列表,确保你改对了文件。
5.2 数据目录权限和配置错误导致服务起不来
服务启动失败的第二个高频原因是数据目录权限不对。Linux 下症状通常是日志里出现[ERROR] Could not open file /var/lib/mysql/ibdata1或者Can't create directory。解决办法是先确认目录所有权:
sudo chown -R mysql:mysql /var/lib/mysql sudo chmod -R 750 /var/lib/mysqlmysqld 进程是以 mysql 用户运行的,如果 data 目录是 root 所有,进程没有写权限,自然起不来。Windows 下如果解压目录的权限不足,也可能出现类似问题,把数据目录放到系统盘之外、不要放在系统权限管理太严的地方。
配置错误主要集中在这几块:
- basedir、datadir 路径不存在或拼写错误。
- my.ini 的编码不对,在 Windows 下保存 my.ini 时如果文件编码带 BOM,会被 mysqld 读成乱码,导致配置项不生效。建议用普通 ANSI 或 UTF-8 无 BOM 保存。
- 端口被占用,上面已经说了。
排查这类问题,必须学会看错误日志。Windows 的数据目录下有一个 .err 文件,里面会写非常具体的启动失败原因。Linux 上则用:
journalctl -u mysql # 或 tail -100 /var/log/mysql/error.log日志里往往会有[ERROR] Aborting这样的行,倒着看最下面的报错就可以定位。
5.3 root 密码忘记与登录认证问题
密码相关的问题,我把它分成两类来说。
第一类:真的忘记 root 密码了。最常用的急救办法是让 MySQL 跳过授权表启动。在 my.cnf 或 my.ini 的[mysqld]段加一行:
skip-grant-tables重启服务后,可以无密码直接登录:
mysql -u root登录后先刷新权限,再重新设置密码:
FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword';改完之后要立刻把配置文件里的 skip-grant-tables 删掉,再重启服务,否则数据库等于不设防。这个方法只建议在单机、可控环境使用,生产环境千万别在未经许可的情况下乱操作。
第二类:密码没错但连接报错。最常见的是认证插件不匹配。报错一般是Authentication plugin 'caching_sha2_password' cannot be loaded。原因是 8.x 默认认证插件是 caching_sha2_password,而老版本的客户端、驱动不认识。解决方案有两个:一是升级客户端驱动,二是把用户改回兼容插件:
ALTER USER 'user'@'host' IDENTIFIED WITH mysql_native_password BY 'password';第二种方案能让老客户端立刻连上,但代价是绕过了默认的安全策略。如果环境允许,我更推荐升级驱动,用 caching_sha2_password。特别提醒一下:不要在生产环境为了临时兼容到处改插件,后面迟早要为这个决定买单。
还有一个非常经典的 Ubuntu 场景:mysql -u root -p输密码错误,其实不是密码错,而是 root 走的是 auth_socket 认证,只有系统 root 或者 sudo 才能连。执行sudo mysql即可进入,想改成密码认证可以执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';5.4 字符集与乱码:utf8mb4 到底怎么设
刚装好的 MySQL,默认字符集可能是 latin1 或者 utf8mb3,这会在后续使用中出现中文乱码、emoji 存不进去等问题。现在统一建议用 utf8mb4,这是真正的四字节 UTF-8,能覆盖绝大多数 Unicode 字符,包括常用表情符号。
检查当前的字符集:
SHOW VARIABLES LIKE 'character_set%';重点关注 character_set_server、character_set_database、character_set_connection 几项。全局修改方式是在配置文件的[mysqld]段加:
character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci在[client]段加:
default-character-set=utf8mb4修改后重启服务。已经建好的库和表,即使改了全局配置也不会自动变更,需要单独执行:
ALTER DATABASE 库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE 表名 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;连接层字符集同样重要。命令行登录时执行SET NAMES utf8mb4;,或者 JDBC 连接串里带characterEncoding=utf8mb4,否则即使库表字符集正确,应用层写入的数据仍可能乱。这里我一直强调“三级字符集”:服务器、数据库、连接,任何一级不对都可能导致乱码,排查时不要只盯数据库一个地方。
最后说点个人体会。我这些年从 5.1、5.5 一路装到 8.x,翻车最多的原因几乎都能追溯到同一个根因:动手之前没确认环境。版本没选好、端口被占、旧版本残留、权限不对,这些其实都不算高深问题,但它们往往比 SQL 优化更磨心态。所以我现在的习惯是:先花五分钟检查环境,再动手安装;卸载的时候永远默认“还有残留”,多删一点都比留一点好。另外,建议每次正式安装前都留一个干净的快照或备份点,不管是虚拟机快照还是 Docker 镜像,真出问题立刻回滚,比现场排查高效得多。希望这篇文章能让你少踩几个我已经踩过的大坑。