1. 为什么不在Ubuntu 22.04默认源里直接装:从8.0到8.4的版本现实
我一开始也以为这事很简单,apt install mysql-server 就行了,结果在 Ubuntu 22.04 上执行完一查版本,看到的是 mysql Ver 8.0.x,不是 8.4。这个现象不是操作失误,而是 Ubuntu 软件源本身的版本策略问题。想在这个系统上装上 MySQL 8.4,就得先搞清楚 Ubuntu 源和 MySQL 官方源之间的这层关系。
1.1 默认源为什么只有8.0
Ubuntu 每个正式版本发布时,会从上游软件仓库中“冻结”一批软件版本,后续只做安全更新和 bug 修复,不会主动升级大版本。Ubuntu 22.04 是 Jammy Jellyfish,它发布的时候,MySQL 社区的主线版本是 8.0 系列,所以官方源里的 mysql-server 就一直停留在 8.0.x。除非你手动添加第三方源或使用 Docker 镜像,否则在 22.04 上直接用 apt 安装,拿到的永远只可能是 8.0。
这里还要注意,Ubuntu 仓库里的 mysql-server 包其实是由 MySQL 官方 APT 源维护者同步构建的,但版本更新节奏和 Ubuntu 的发布周期强绑定。如果只是做日常开发,8.0 够用;可如果团队内部已经使用了 MySQL 8.4 的某些新特性,或者你的生产环境希望和官方 LTS 版本保持一致,那就必须绕过 Ubuntu 默认源,走 MySQL 官方 APT 仓库。
1.2 MySQL 8.4 LTS 和8.0/8.1+是什么关系
MySQL 从 8.1 开始调整了版本发布模式:8.1、8.2、8.3 这些属于 Innovation 版本,功能迭代快,但每个版本的支持周期短,不适合生产环境长期部署。8.4 是这条新版本线里的第一个 LTS 版本,官方提供长期支持,安全更新和维护周期更长。所以从生产运维角度看,8.4 是接替 8.0 的稳妥选择,而不是 8.1 或者 8.3 这种过渡版本。
8.4 和 8.0 在核心使用上差别不算大,SQL 语法、InnoDB 引擎、主从复制、备份恢复这些基础能力都是一脉相承的。但它对默认安全性做了不少收紧,比如默认禁用了一些旧认证插件,调整了部分系统变量默认值。这些东西如果你是从 8.0 升级上来的老用户,可能会在部署完成后发现某些配置不生效,这个我后面会专门说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署前调整:添加MySQL官方APT源的三步准备
既然 Ubuntu 自带源没有 8.4,那思路就清楚了:添加 MySQL 官方 APT 仓库,让系统能从官方源里拿到 mysql-server 8.4 版本。这一步听起来简单,但有几个细节会导致后面安装失败或版本不对,我按顺序拆开讲。
2.1 更新系统并安装必要依赖
在添加任何第三方源之前,先把系统基础环境准备好。登录 Ubuntu 22.04 后,先执行:
bash复制sudo apt update
sudo apt upgrade -y
然后安装几个后面会用到的工具包。gnupg 是用来导入 GPG 密钥的,wget 用来下载配置包,lsb-release 和 ca-certificates 是 MySQL 源配置脚本依赖的一部分:
bash复制sudo apt install -y wget gnupg lsb-release ca-certificates
这一步不要跳过。有些用户系统里没有 lsb-release,安装 MySQL 官方源配置包时脚本会报“无法识别发行版”的错误,虽然可以通过手动写源文件绕过去,但没必要给自己添麻烦。
2.2 下载并安装MySQL APT配置包
MySQL 官方提供了一个 APT 仓库配置包,文件名叫 mysql-apt-config_*.deb。不同时间下载到的具体文件名可能不一样,我建议在部署前先到 MySQL 官方下载页面查一下当前版本号,但通常直接使用下面的方式也可以:
bash复制wget https://dev.mysql.com/get/mysql-apt-config_0.8.33-1_all.deb
sudo dpkg -i mysql-apt-config_*.deb
执行 dpkg -i 后,会弹出一个图形化的配置界面。这一步很关键:你需要选择 MySQL Server & Cluster,然后在版本列表里选择 mysql-8.4-lts,不是默认的 mysql-8.0。如果手滑选了 8.0,后面安装出来还是老版本。
选好后,界面会回到主菜单,选择 OK 退出。然后立刻更新 apt 缓存:
bash复制sudo apt update
更新过程会从 MySQL 官方源获取 8.4 的软件包列表。如果看到 GPG 错误,多半是公钥没有正确导入,我后面在踩坑记录章节里会详细说。
2.3 查看源文件确认版本来源
配置完成后,不要急着安装,先确认源文件写对了。查看 /etc/apt/sources.list.d/mysql.list,里面应该能看到类似这样的内容:
bash复制deb http://repo.mysql.com/apt/ubuntu jammy mysql-apt-config
deb http://repo.mysql.com/apt/ubuntu jammy mysql-8.4-lts
deb-src http://repo.mysql.com/apt/ubuntu jammy mysql-8.4-lts
如果你只看到 mysql-apt-config,没有 mysql-8.4-lts,说明刚才交互界面里没选对,重新执行 sudo dpkg-reconfigure mysql-apt-config 再选一次。
最后用 apt-cache policy 验证一下当前候选版本:
bash复制apt-cache policy mysql-server
输出里的 Candidate 应该显示 8.4.x 系列版本。只要这一步正确,后面安装就是水到渠成的事。
3. 安装与初始化:从apt install到安全加固的完整链路
源准备好之后,真正安装 MySQL 8.4 反而是最顺利的环节。但安装完成不等于部署完成,初始化、启动、安全加固这三步都做完,才算一个能用的数据库服务。
3.1 正式安装mysql-server
直接执行:
bash复制sudo apt install -y mysql-server
这会根据 apt 源里的候选版本,自动安装 mysql-server 对应的 8.4 系列版本依赖。安装过程中,系统可能会弹出一个对话框,要求设置 MySQL root 用户的密码。这里要注意:MySQL 官方 APT 包的安装方式和 Ubuntu 默认源不太一样,如果安装界面出现,最好输入一个强密码;如果留空,MySQL 会使用默认的认证方式,后面可能会遇到 sudo mysql 能进、mysql -uroot -p 却进不去的情况。
安装完成后检查版本:
bash复制mysql --version
正常会输出类似 mysql Ver 8.4.x for Linux on x86_64 的信息。如果这里仍然显示 8.0,说明源没生效,或者 apt 缓存没有更新成功,回到上一章重新检查。
3.2 启动服务并检查状态
Ubuntu 22.04 使用 systemd 管理服务。安装完成后 MySQL 服务通常已经启动,但我们还是要显式地设置开机自启并确认运行状态:
bash复制sudo systemctl enable --now mysql
sudo systemctl status mysql --no-pager
如果状态是 active (running),说明服务正常。接着看端口监听情况:
bash复制sudo ss -lntp | grep 3306
默认配置下 MySQL 会监听 127.0.0.1:3306,这个符合安全预期。如果这时候直接看到 0.0.0.0:3306,说明默认配置允许外部连接,需要检查一下是否真的需要暴露数据库端口。
使用 root 进入数据库也有两种方式。如果安装时没有设置 root 密码,可以尝试:
bash复制sudo mysql
这个命令会通过 Unix socket 认证方式,以系统 root 身份直接进入 MySQL。如果安装时设置了密码,就用:
bash复制mysql -uroot -p
输入刚才的密码进入。
3.3 执行mysql_secure_installation
MySQL 8.4 安装后的基础配置里,会保留匿名用户、测试数据库和 root 远程登录能力,这些在生产环境都是安全风险。官方提供的 mysql_secure_installation 脚本就是用来一键清理这些隐患的。
bash复制sudo mysql_secure_installation
这个脚本会逐步提问,通常包括:
- 是否使用密码强度校验插件
- 是否修改 root 密码
- 是否删除匿名用户
- 是否禁止 root 远程登录
- 是否删除 test 数据库
- 是否刷新权限表
我个人的建议是:密码校验插件根据团队密码规范来,如果有统一的密码管理平台,可以不开,避免强制复杂度导致应用侧密码不符合要求;但匿名用户和 test 数据库一定要删,root 远程登录一定要禁止。
这一步做完,数据库服务的基本安全底线就立住了。
4. 配置落盘:字符集、数据目录和连接层的关键参数
安装完只是“能用”,接下来要往里写配置。MySQL 的配置项很多,但 Ubuntu 22.04 部署 8.4 时,我主要关心四个东西:配置文件加载逻辑、字符集、数据目录位置、连接数相关参数。
4.1 配置文件的读取逻辑
Ubuntu 上通过 apt 安装的 MySQL,配置文件入口是 /etc/mysql/my.cnf,但这个文件本身内容很少,它通过 !includedir 指令引入了两个目录:
ini复制!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
所以不要直接去改 /etc/mysql/my.cnf,更不要觉得“配置文件只有一个”。正确做法是在 /etc/mysql/mysql.conf.d/ 目录下新建一个独立配置文件,比如 mysql-8.4-custom.cnf,然后在里面写自定义配置。这样做的好处是升级软件包时不会被覆盖,排查问题时把自定义文件临时改名就能快速恢复默认行为。
4.2 字符集与排序规则
MySQL 8.0 开始默认字符集就是 utf8mb4,8.4 延续了这个默认值,但我依然建议显式写进配置里,避免某些迁移场景下继承旧库的 latin1 设置。在 /etc/mysql/mysql.conf.d/mysql-8.4-custom.cnf 中写入:
ini复制[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci
[client]
default-character-set = utf8mb4
这里 utf8mb4_0900_ai_ci 是 MySQL 8.x 默认的排序规则,比老的 utf8mb4_general_ci 更准确。如果应用里有特殊需求,比如大小写敏感或二进制比较,可以按需调整,但普通业务场景用默认即可。
修改后重启服务:
bash复制sudo systemctl restart mysql
然后进入数据库验证:
sql复制SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'collation_server';
两条结果都应该是 utf8mb4 和 utf8mb4_0900_ai_ci。
4.3 数据目录迁移:改完配置还要处理AppArmor
很多服务器会把系统盘和数据盘分开,默认数据目录 /var/lib/mysql 可能不在数据盘上。如果你也需要迁移数据目录,这里有一个 Ubuntu 特有的坑:AppArmor。
首先,用 rsync 复制数据目录:
bash复制sudo systemctl stop mysql
sudo mkdir -p /data/mysql
sudo rsync -av /var/lib/mysql/ /data/mysql/
sudo chown -R mysql:mysql /data/mysql
然后修改配置:
ini复制[mysqld]
datadir = /data/mysql
如果你直接用 systemctl start mysql,大概率会启动失败,日志里会出现类似 AppArmor parser error 或 Permission denied。原因就是 AppArmor 默认只允许 mysqld 访问 /var/lib/mysql/。
解决方法是编辑 AppArmor 配置:
bash复制sudo vim /etc/apparmor.d/usr.sbin.mysqld
把里面的 /var/lib/mysql/ 相关路径改成新路径,或者添加:
text复制/data/mysql/ r,
/data/mysql/** rwk,
然后重新加载 AppArmor 配置并启动 MySQL:
bash复制sudo systemctl reload apparmor
sudo systemctl start mysql
这一步不处理,后面无论怎么调权限都起不来。这也是我在 Ubuntu 22.04 上部署 MySQL 8.4 时印象最深的一个坑。
4.4 连接数、超时与DNS反查
生产环境里,数据库连接数设置不当是常见的故障源头。在配置文件中可以按实际业务调整:
ini复制[mysqld]
max_connections = 500
wait_timeout = 600
interactive_timeout = 600
skip-name-resolve
skip-name-resolve 表示禁止 MySQL 对客户端 IP 做反向 DNS 解析。这个参数对连接速度有明显帮助,尤其是高并发场景下,避免每次连接都去查 DNS。但注意,开启后,授权表里的 host 字段就只能用 IP 地址,不能用域名。
这里要提醒一句:max_connections 不是越大越好。每一条连接都需要消耗内存,连接数过多会把服务器内存吃满。一般按 (可用内存 - 系统预留) / 单连接内存 来估算,不要拍脑袋写几千。
5. 业务账号与远程访问:授权时最容易翻车的几个点
数据库装好、基础配置写完,接下来就是给业务创建账号。这个环节看着简单,但权限、主机、认证插件、bind-address、防火墙五个小问题,任何一个没配好,应用就连不上。
5.1 创建账号与授权语法
使用 root 登录 MySQL 后,创建一个业务账号:
sql复制CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'YourStrongPassword';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'192.168.1.%';
FLUSH PRIVILEGES;
这里 '192.168.1.%' 表示允许来自 192.168.1.0/24 网段的连接。如果应用和数据库在同一台机器上,可以只授权 localhost;如果有多个应用服务器,建议按网段授权,不要直接写 %,避免账号暴露到整个网络。
MySQL 8.4 的授权体系和 8.0 一致,账号能拿到什么权限,在 GRANT 时就确定好了。最小的权限原则不光是安全要求,也能避免业务账号误操作删除数据。
5.2 查询用户与授权信息
创建完成后,检查一下账号状态:
sql复制SELECT user, host, plugin FROM mysql.user WHERE user = 'app_user';
SHOW GRANTS FOR 'app_user'@'192.168.1.%';
这里 plugin 列很重要。MySQL 8.4 默认认证插件是 caching_sha2_password,这是比较新的密码认证方式。如果你看到的是 mysql_native_password,那说明系统配置可能被改过,或者创建账号时显式指定了旧插件。从安全角度讲,8.4 不建议再用旧插件。
5.3 bind-address与防火墙
默认配置下,MySQL 只监听 127.0.0.1,其他机器连不上。要让远程访问生效,需要修改配置文件:
ini复制[mysqld]
bind-address = 0.0.0.0
然后重启 MySQL:
bash复制sudo systemctl restart mysql
如果是在 Ubuntu 22.04 上开启了 ufw 防火墙,还要放行端口:
bash复制sudo ufw allow from 192.168.1.0/24 to any port 3306
这里不建议直接 sudo ufw allow 3306,因为那会暴露给所有外部 IP。用来源网段限制是更稳妥的做法。
最后在另一台机器上测试:
bash复制mysql -h 数据库IP -P 3306 -u app_user -p
连接失败时,先看 MySQL 日志 /var/log/mysql/error.log,再查 ufw 状态,最后检查 bind-address。排查链路固定下来,基本几分钟就能定位。
5.4 认证插件导致的客户端兼容问题
如果应用服务器上的客户端版本比较老,比如 5.7 时代编译的驱动,连接时可能会报:
text复制Authentication plugin 'caching_sha2_password' cannot be loaded
这是 8.x 系列最常见的问题。MySQL 8.4 默认禁用 mysql_native_password 插件,官方建议的方式是升级客户端驱动。你可以用下面的命令确认当前账号使用的插件:
sql复制SELECT user, host, plugin FROM mysql.user;
如果你的客户端实在无法升级,就需要在配置文件中显式启用旧插件:
ini复制[mysqld]
mysql_native_password=ON
然后在创建账号时指定:
sql复制CREATE USER 'old_client'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
但我要提醒一句:这个兼容方式能不开就不开,它会让密码校验能力和默认安全基线下降。最好还是让开发团队把驱动升级到支持 caching_sha2_password 的版本。
6. 部署后的稳定性检查:systemd、日志和备份兜底方案
数据库部署完成不等于事情结束。能不能稳定跑下去,取决于开机自启、日志监控、备份恢复三个维度。我习惯在部署完当天就把这套兜底方案做掉。
6.1 systemd服务管理细节
MySQL 8.4 在 Ubuntu 22.04 上使用 systemd 管理,相关命令:
bash复制sudo systemctl enable mysql
sudo systemctl restart mysql
sudo systemctl status mysql --no-pager
sudo systemctl disable mysql
查看服务是否开机自启:
bash复制systemctl is-enabled mysql
如果显示 enabled,说明没问题。如果显示 disabled,执行一次 sudo systemctl enable mysql。
另外,systemd 的 service 文件里可能包含 ProtectSystem、ProtectHome 等安全限制。如果你在自定义配置中使用了非常规路径,比如把 socket 文件放到 /tmp 下,可能会被 systemd 的 PrivateTmp 干扰。遇到 socket 无法访问时,先检查 /lib/systemd/system/mysql.service 里的安全选项。
6.2 日志、状态与性能基线
MySQL 的错误日志默认在 /var/log/mysql/error.log。日志记录了启动过程、连接异常、权限错误、主从状态变化等信息。部署完当天,我建议执行一遍“健康巡检”:
sql复制SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Aborted_connects';
SHOW VARIABLES LIKE 'log_error';
Threads_connected 可以观察当前连接数,Aborted_connects 如果快速增长,说明可能有客户端频繁认证失败,要认真查一下来源。
如果想简单压一下数据库底子,可以用系统自带的 mysqlslap:
bash复制mysqlslap --user=root --password --concurrency=50 --iterations=5 --number-of-queries=1000 --auto-generate-sql
这个工具可以模拟并发查询,不需要额外安装。压测结果不追求极限性能,主要是看看数据库能不能在预期并发下稳定响应。
6.3 备份兜底:mysqldump + binlog
备份是数据库运维里永远不能跳过的一步。MySQL 8.4 支持 mysqldump,对于中小规模业务,配合 binlog 可以做全量+增量恢复。
最简单的一次全量备份脚本:
bash复制#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
mysqldump \
--single-transaction \
--set-gtid-purged=OFF \
--all-databases \
--routines \
--triggers \
--events \
-u root -p > "$BACKUP_DIR/full_$DATE.sql"
--single-transaction 可以在 InnoDB 表上拿到一致性的备份点,不会锁表。--set-gtid-purged=OFF 对于单机环境恢复更方便;但如果后续要做主从复制,可能需要改成 ON,这点要结合你的复制策略来。
备份文件建议再传到独立存储,不要只留在数据库机器上。再补个 crontab 定时任务:
bash复制0 2 * * * /usr/local/bin/mysql_backup.sh
这样每天凌晨两点自动备份,遇到问题至少能恢复到前一天。
6.4 日志轮转
MySQL 错误日志通常由 logrotate 管理,配置文件在 /etc/logrotate.d/mysql-server。默认策略是按天或按大小轮转,保留一定份数。不用太操心,但部署后可以检查一下这个文件是否存在:
bash复制cat /etc/logrotate.d/mysql-server
如果不存在,说明软件包没带默认配置,需要手动补一个。否则磁盘被 error.log 写满时,MySQL 可能拒绝写入,甚至导致服务异常。
7. 踩坑记录:我在22.04装8.4时遇到的三类问题
最后这部分是我实际部署中遇到过的问题,不是网上随便找的案例。每个问题都踩过一遍,记录在这里,希望能帮你节省排查时间。
7.1 apt-key 过期与GPG密钥导入报错
很多老教程会让你用 apt-key 导入 MySQL 官方公钥,但 Ubuntu 22.04 已经对 apt-key 给出 deprecated 警告,继续使用也可能遇到密钥过期。而 MySQL 官方 APT 配置包在安装时会自动处理公钥,不需要手动导入。如果你在 sudo apt update 时看到 NO_PUBKEY,可以重新安装配置包,或者手动从 MySQL 官方站点下载对应的 GPG 密钥文件导入。不要尝试用一堆 apt-key 命令自己去“修复”,那样通常只会制造新的密钥冲突。
7.2 AppArmor拦住了迁移后的数据目录
我前面专门提过数据目录迁移,这里再强调一下原因。我一开始迁移完数据目录后,修改 datadir 并启动 MySQL,发现服务一直在重启。查看日志才看到 AppArmor 拒绝访问新目录。当时第一反应是文件权限问题,反复 chown 都没有效果,后来才意识到是 AppArmor 在起作用。Ubuntu 上调整 MySQL 数据目录,必须同步调整 AppArmor profile,否则 MySQL 进程没有权限访问新目录。这个问题在 CentOS 上不存在,但在 Ubuntu 上几乎是必踩项目。
7.3 老客户端连不上MySQL 8.4
上线时遇到一个比较典型的兼容性问题:内部有个老系统用的 JDBC 驱动版本比较旧,连接 MySQL 8.4 时报 Public Key Retrieval is not allowed。这个错误和 caching_sha2_password 有关,新认证插件在非加密连接下需要获取公钥来交换密码,而老驱动默认不允许这个行为。
如果不升级驱动,有两个临时绕过方案:在 JDBC URL 上加 allowPublicKeyRetrieval=true,或者把账号认证插件改成 mysql_native_password。但这两个方案都不是长久之道,安全性和长期兼容性都不如直接升级驱动。最后我推动了驱动升级,连接问题彻底消失,也没必要在 MySQL 侧降低安全等级。
7.4 修改端口后systemd和selinux/AppArmor的连锁反应
如果你把 port 从 3306 改成 63306,不要只改配置文件。第一步,确认 AppArmor 是否限制了 mysqld 监听非标准端口;第二步,在防火墙放行新端口;第三步,检查业务侧连接的端口是否同步更新。我见过很多只改配置不刷 AppArmor 的例子,服务重启后依然监听旧端口,因为新端口被安全策略拦住了。
总体来说,在 Ubuntu 22.04 上部署 MySQL 8.4,最难的部分不是安装本身,而是被 Ubuntu 的源策略、AppArmor、认证插件这几个系统级机制卡住。只要把版本源选对、AppArmor 处理好、客户端认证方式确认清楚,整个部署流程还是相当顺的。我在后续部署新服务器时已经把这套流程固化成脚本,从添加源到安全初始化基本十分钟内完成,这也是自己踩坑后最大的收获。
