
2. 实操过程与核心环节实现既然是把 MySQL 跑在 Ubuntu 22.04 上我默认你已经有一台装好系统的机器不管是物理机、虚拟机还是云主机都行。我自己那台测试机是 22.04.3 LTS内存给了 4G磁盘 50G这个配置跑 MySQL 8.0 完全够用。下面整个安装配置流程我都会基于这个环境来写。2.1 换源先把 apt 源切到国内镜像这一步不是必须的但是强烈建议。Ubuntu 22.04 默认的源服务器在国外国内网络环境下apt update可能要等很久下载 MySQL 服务端那几个包更是一个煎熬的过程。我自己习惯用阿里云镜像稳定且同步频率高。操作方式很简单先备份原始源文件sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后用编辑器打开/etc/apt/sources.list把里面的地址批量替换成阿里云地址。Ubuntu 22.04 的源地址格式是http://archive.ubuntu.com/ubuntu/替换为http://mirrors.aliyun.com/ubuntu/其他部分保持不动。也可以直接使用sed命令全局替换sudo sed -i s/archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list替换完以后执行sudo apt update如果看到更新列表正常拉到说明源已经生效了。这里有一个坑Ubuntu 22.04 默认启用了 APT 的by-hash机制偶尔会遇到哈希验证失败的情况原因多半是镜像站同步延迟。遇到这种问题不必慌张过几分钟再跑一次apt update基本就恢复了。2.2 正式安装 MySQL 8.0执行安装命令之前可以先用下面的命令确认一下软件源里 MySQL 的版本apt policy mysql-server正常会显示候选版本是8.0.x。确认无误后执行sudo apt update sudo apt install mysql-server -y这个过程会自动安装 MySQL 的服务端、客户端以及一系列依赖包。Ubuntu 22.04 的mysql-server包名对应的是 MySQL 8.0安装完不需要额外配置官方源就能直接获得较新版本这是它比 CentOS 7 那种老环境舒服很多的地方。安装完成后先看一眼服务状态sudo systemctl status mysql如果看到active (running)说明服务已经起来了。顺便说一句Ubuntu 22.04 上 MySQL 的服务名就是mysql有些教程写成mysqld那是 CentOS 系的叫法在 Ubuntu 上直接照搬会提示找不到服务这一点留意一下。2.3 初始化配置跑一遍 mysql_secure_installation刚装完的 MySQL 处于一个裸奔状态默认的 root 账号使用的是auth_socket认证插件这个插件的特点是只要你是 Linux 的 root 用户通过 socket 连接 MySQL 就能直接以 root 身份登录完全不需要密码。这个机制本地开发用着很方便但如果是生产环境显然不够安全。Ubuntu 官方提供的初始化脚本是mysql_secure_installation它会引导你完成一系列安全加固操作。在终端里直接执行sudo mysql_secure_installation脚本会一步步问你几个问题是否设置密码校验强度。MySQL 8.0 提供三种级别LOW、MEDIUM、STRONG。测试环境建议选LOW或者直接输 N 跳过密码规则太严格反而容易给自己找麻烦生产环境至少选MEDIUM也就是要求密码包含数字、大小写字母和特殊字符。是否修改 root 密码。这一步需要你在上面确认了校验强度之后设置新密码。是否删除匿名用户。必须选 Y。是否禁止 root 远程登录。看需求如果你的应用需要从别的机器连 MySQL建议选 N后续通过创建专用账号来控制访问权限如果只是本机使用选 Y 更安全。是否删除 test 数据库并刷新权限表。都选 Y 就行。跑完以后 MySQL 的基础安全配置就差不多了。这里要重点说一下auth_socket的问题。Ubuntu 22.04 默认安装的 MySQL 8.0root 用户默认是通过socket认证而不是caching_sha2_password这意味着你在应用里用 root 加密码去连接数据库会直接报错Access denied。我后续会专门写一节来讲这个问题的解决方案因为这是 Ubuntu 上装 MySQL 最容易踩的坑没有之一。3. 核心细节解析与实操要点这一节把整个配置过程中几个容易被忽略、但是又至关重要的细节单独拎出来详细讲。3.1 彻底搞懂 root 用户的 auth_socket 认证用sudo mysql能直接进 MySQL但用mysql -u root -p输入密码却进不去——这种现象几乎每个 Ubuntu 用户都遇到过。原因在于 Ubuntu 的 MySQL 包默认把 root 账号的认证插件设成了auth_socket。它做的认证机制是检查当前 Linux 系统用户的身份如果与 MySQL 用户匹配并且是通过本地 socket 文件连接就直接放行无视密码。查看当前 root 用户的认证方式SELECT user, host, plugin FROM mysql.user WHERE user root;执行结果大概率是------------------------------ | user | host | plugin | ------------------------------ | root | localhost | auth_socket | ------------------------------如果想让 root 也走密码认证可以执行ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY 你的密码; FLUSH PRIVILEGES;但我的建议是不要改动 root 的认证方式保持auth_socket不变。原因有两个。第一root 走 socket 认证意味着只有 Linux 的 root 用户才能以数据库 root 身份登录这本身就是一道很强的系统级防线第二日常开发和运维应该用普通账号root 留给紧急情况时使用。需要远程访问时另外创建一个专用账号并限定主机名和权限这样既安全又灵活。3.2 MySQL 8.0 默认字符集配置先把 utf8mb4 安排好MySQL 8.0 开始默认字符集已经是utf8mb4了比 5.7 时代默认的latin1先进了不少。但为了保险起见我建议在配置文件里显式声明避免将来其他同事或脚本不小心改了全局变量导致乱码。MySQL 8.0 的配置文件位置和 5.7 时代不太一样。Ubuntu 上 MySQL 的配置目录是/etc/mysql/主配置文件是/etc/mysql/mysql.conf.d/mysqld.cnf而不是传统印象里的/etc/my.cnf。在[mysqld]段下追加character-set-server utf8mb4 collation-server utf8mb4_unicode_ci skip-character-set-client-handshakeskip-character-set-client-handshake的作用是忽略客户端连接时指定的字符集强制使用服务端的 utf8mb4省掉客户端那边一堆没必要的字符集转换问题。改完配置记得重启 MySQLsudo systemctl restart mysql登录后执行SHOW VARIABLES LIKE character%;检查是否全部变成 utf8mb4。3.3 配置文件里值得调整的参数除了字符集还有几个参数在实际使用中几乎每次都要调整。先说bind-address这个参数默认是127.0.0.1意思是只允许本机连接。如果你的应用服务和数据库不在同一台机器就需要把它改成0.0.0.0。但这里有个安全注意点直接监听所有网卡意味着任何能访问到你机器 IP 的人都可能尝试连接数据库所以必须配合防火墙限制和账号权限控制一并处理。再说连接数限制MySQL 8.0 默认的max_connections是 151对大多数中小型应用够用了但如果你的应用有连接池或者并发量比较高可能会频繁出现Too many connections的报错。可以把值调到 300 或者更高同时要注意操作系统的ulimit限制否则 MySQL 进程可能无法创建足够的线程。我整理了一份比较实用的基础配置模板[mysqld] bind-address 0.0.0.0 port 3306 character-set-server utf8mb4 collation-server utf8mb4_unicode_ci max_connections 300 default-time-zone 08:00default-time-zone这个参数很容易被忽略。如果你的服务器时区不是中国标准时间而应用代码又是按照北京时间来处理的DateTime 字段的存取就会出现 8 小时的偏差。与其在代码里做时区转换不如直接从数据库层面统一掉。4. 常见问题与排查技巧实录以下这些问题是国内社区里关于 Ubuntu 22.04 安装 MySQL 提问频率最高的一批我把排查思路和解决方案统一整理出来。4.1 远程连接报错Host xxx is not allowed to connect这个报错的原因是 MySQL 默认只允许 root 从 localhost 登录其他主机的连接请求一律拒绝。解决办法不是在 root 上授权而是创建一个专门供远程使用的账号CREATE USER appuser% IDENTIFIED BY 强密码; GRANT ALL PRIVILEGES ON appdb.* TO appuser%; FLUSH PRIVILEGES;appuser%中的%表示允许来自任意主机的连接。出于安全考虑最好把%换成应用服务器的实际 IP比如appuser192.168.1.100。同时检查配置文件里bind-address是否为0.0.0.0以及防火墙是否放开了 3306 端口。4.2 Navicat 连接时报错Authentication plugin caching_sha2_password cannot be loadedMySQL 8.0 默认的认证插件是caching_sha2_password而老版本 Navicat尤其是 12 以前的版本只支持mysql_native_password两者不兼容就会报这个错。解决方案有两个第一种解决方案是升级 Navicat 到 16 以上的版本官方早就支持了caching_sha2_password。第二种方案是把用户的认证插件改回旧版ALTER USER appuser% IDENTIFIED WITH mysql_native_password BY 密码; FLUSH PRIVILEGES;我的建议是优先选择升级客户端毕竟mysql_native_password在 MySQL 8.0 里已经被标记为废弃插件迟早要淘汰。但如果你的生产环境有一些老系统没法升级驱动第二种方案作为过渡手段也是合理的。4.3 忘记 root 密码后的恢复流程这个场景几乎所有人都会经历一次。MySQL 8.0 的密码恢复流程和 5.7 不太一样不能再简单地用skip-grant-tables跳过权限表然后直接 UPDATE 用户表了因为 8.0 的认证逻辑比 5.7 复杂直接改密码字段很可能不生效。正确姿势是sudo systemctl stop mysql sudo mkdir -p /var/run/mysqld sudo chown mysql:mysql /var/run/mysqld sudo mysqld_safe --skip-grant-tables --skip-networking --skip-networking必须加上它能让 MySQL 只监听本地 socket防止你在恢复密码的过程中数据库被外部连接。之后用 root 登录sudo mysql -u root在 MySQL 中执行FLUSH PRIVILEGES; ALTER USER rootlocalhost IDENTIFIED BY 新密码; FLUSH PRIVILEGES;最后重启服务恢复正常模式。4.4 腾讯云/CVM 用户专属坑防火墙规则放行了但连不上很多云服务器用户遇到的问题是bind-address改了MySQL 账号也授权了本地也能登录但远程就是连不上。这时候先检查云平台的安全组规则因为云主机的防火墙有两层——除了系统层面的 iptables还有云平台控制台里的安全组。安全组默认只放行了 22 端口3306 需要在控制台额外添加规则。不少人在系统里折腾半天结果发现是安全组没放行这个排查思路一定要有这个意识。另外一个容易被忽略的问题是 UFW 防火墙。Ubuntu 默认没有启用 UFW但有些教程会让你开启。如果启用了记得执行sudo ufw allow 3306/tcp如果不想对所有 IP 开放可以在命令后面加上具体的来源 IP只允许那一台机器访问。4.5 中文乱码问题虽然 8.0 默认字符集是 utf8mb4但乱码问题还是会以各种形式出现。最常见的情况是数据库和表都是 utf8mb4但连接层指定了别的字符集。如果你用了 3.2 里提到的skip-character-set-client-handshake基本上能杜绝这个问题。如果已经出现了乱码检查链路客户端工具或 JDBC URL 里是否指定了characterEncodingutf8特别注意 JDBC 里的utf8和 MySQL 里的utf8mb4不是一个概念如果你原来用的是utf8建议改成utf8mb4。4.6 服务启动失败Job for mysql.service failed这种问题多半是配置文件写错了。Ubuntu 上 MySQL 对配置文件的语法比较敏感任何一个参数名拼错或者配置段写错都会导致服务起不来。遇到这种情况先查看错误日志sudo journalctl -u mysql.service tail -f /var/log/mysql/error.log日志会非常明确地告诉你哪一行配置出了问题。把对应的行修掉再systemctl restart mysql即可。4.7 MySQL 5.7 升级到 8.0 的注意事项如果你是从 5.7 升级到 8.0需要提前了解一些兼容性问题。5.7 里一些非标准的 SQL 写法在 8.0 里会被直接拒绝比如GROUP BY的隐式排序、WITH子句的保留关键字等。还有 API 和驱动兼容性MySQL 8.0 的认证插件变了老版本的 JDBC 驱动会报错需要把驱动升级到mysql-connector-java 8.x。如果要升级的是生产库先找一台测试机演练一遍再考虑操作线上环境。5. 从安装到日常维护再说几个实在的体会MySQL 装好、配置好、能连上这只是开始。后面日常维护中有几个点我用下来感觉特别值得花时间提前弄好。第一个是自动备份。用crontab配合mysqldump写一个简单的定时备份脚本每天凌晨跑一次备份文件保留七天基本能应对绝大多数误删和误操作场景。我自己吃过亏所以对备份这个事特别敏感。脚本也不复杂几十行就能搞定关键是要记得把备份文件同步到另一台机器或对象存储防止服务器硬盘本身挂掉导致备份跟着一起丢。第二个是慢查询日志。MySQL 8.0 默认不开启慢查询日志但排查接口性能问题时这个日志是最直接的切入点。在配置文件里加上slow_query_log 1 slow_query_log_file /var/log/mysql/slow.log long_query_time 2这样执行时间超过两秒的 SQL 都会被记录下来配合mysqldumpslow或pt-query-digest分析定位慢查询特别方便。第三个是资源监控。建议装一个prometheus mysqld_exporter把 MySQL 的关键指标采集起来配合 Grafana 做可视化看板。如果不想搭这么一套重的东西至少可以每天看一眼SHOW GLOBAL STATUS里几个关键指标Threads_connected、Questions、Slow_queries。这些数据能直观反映数据库的健康状况。第四个是连接数管理。连接池配置不当是导致 MySQL 被打挂的最常见原因。应用连接池的上限一定要小于 MySQL 的max_connections并且要给数据库预留一部分连接用于运维操作。假设你有三个应用服务每个连接池上限 100MySQL 的max_connections哪怕设了 300也扛不住瞬间的流量高峰。合理规划连接池大小再加上wait_timeout和interactive_timeout的配合让空闲连接及时回收这一块做好了能让数据库稳很多。现在再回头看整个 Ubuntu 22.04 装 MySQL 的过程其实真正的难点从来不是跑那几条安装命令而是安装完之后的配置思路和安全意识。写这篇东西的时候我把这几年在数据库维护中踩过的坑、总结的经验都带了进来就是想让你少走一些弯路把这些经验直接拿去用。最后再分享一个小技巧装好之后立刻执行一遍mysql_secure_installation并且不要跳过任何一步。很多人觉得这个脚本啰嗦嫌它要回答一堆问题于是直接 CtrlC 跳过。但等你哪天真被拖库了回过头来才会觉得那个啰嗦的脚本是多么可爱。安全这种东西多一分准备就少一分意外。