ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ubuntu 24.04 安装配置 MySQL 8:认证插件、远程连接与安全加固

Ubuntu 24.04 安装配置 MySQL 8:认证插件、远程连接与安全加固 如果你的 Ubuntu 24.04 刚装上想跑 MySQL 8第一反应多半是sudo apt install mysql-server。这套操作在 20.04、22.04 上都挺顺畅但到了 24.04 这个 LTS 上有几个细节稍微不一样认证插件、软件源版本、systemd 服务命名碰到一次就很耽误事。这篇文章是我最近在一台全新 Ubuntu 24.04 服务器上安装 MySQL 8 的完整记录包括安装、初始化、远程访问、安全加固和几个高频报错的处理思路适合准备用 MySQL 8 做开发环境或小规模生产的同学参考。我会尽量把每一步的命令、预期输出、出错场景都写清楚还会把网上顺手抄来的“经验”对照实际行为给过滤一遍——比如 24.04 里 root 为什么能免密登录、为什么改了 bind-address 还是连不上、以及那个和 MySQL 无关的 gdb 服务报错该怎么隔离排查。这些内容你在官方文档里也能找到但散在各处我帮你串成一条能顺着一路跑完的路径。1. 为什么在 Ubuntu 24.04 上安装 MySQL 8 之前要先想清楚这几个问题1.1 这个 LTS 仓库里的 MySQL 到底是什么版本Ubuntu 24.04Noble Numbat默认软件源里带的 MySQL 是 8.0.x 系列我安装时拿到的是mysql-server-8.0这个包实际版本号类似8.0.36-0ubuntu0.24.04。也就是说你只要用apt装装到的就是社区版 MySQL 8.0不需要再去官网下载.deb包。这一点值得先确认因为网上大量教程还停留在 MySQL 5.7 的思维模式甚至有的会让你自己去官方仓库添加 deb 源。纯从“跑起来”这个需求看官方仓库没必要碰原因后面会讲。查看版本可以用两条命令mysql --version或者dpkg -l | grep mysql-server正常会输出类似mysql-server-8.0和mysql-client-8.0两个包。如果你手头是刚装的 24.04 最小化系统mysql命令可能还不存在这是正常的装完mysql-server之后客户端也会一起装好。1.2 认证插件的变化和兼容性MySQL 从 8.0 开始把默认认证插件改成了caching_sha2_password替代了老的mysql_native_password。这个改动的一个直接后果是如果你用 PHP 7.1 以下、老版本 Navicat、或者某些过时的 Python MySQL 驱动去连报错会非常玄学常见提示是Authentication plugin caching_sha2_password cannot be loaded。但 Ubuntu 仓库里的 MySQL 8.0 还有一个更特殊的默认行为它在安装后自动初始化的 root 用户默认走了auth_socket插件。也就是说你在本机直接执行sudo mysql就能进入根本不用密码。这是 Debian/Ubuntu 系为了系统集成故意设置的很多第一次用的人会愣住怎么没密码就进去了这其实不是漏洞是设计如此。理解这两层之后你才能决定后面到底要不要改认证方式、怎么建业务账号。我见过很多人一上来就把 root 改成mysql_native_password反而把自己的安全防线拉低了。1.3 apt 安装和官方仓库安装应该怎么选这里有个实际问题到底用 Ubuntu 自带的软件源还是用 MySQL 官方 apt 仓库我的建议是如果没有特殊理由直接用 Ubuntu 仓库。原因有三个。第一Ubuntu 仓库的包经过了对系统版本、系统库的适配依赖冲突少第二安全更新跟着系统一起走运维省心第三24.04 仓库里的版本就是 8.0.x足够满足绝大多数需求。而 MySQL 官方 apt 仓库里现在已经提供 8.4 LTS 和更新版本。如果你从官方仓库装命令虽然还是apt install mysql-server但装到的可能是完全不同的版本线默认行为也变了——比如 8.4 里mysql_native_password被移到单独实现里老教程里的ALTER USER ... IDENTIFIED WITH mysql_native_password不一定还能直接生效。网上一堆教程就是对不上这种情况所以我建议新手走 Ubuntu 仓库少踩一个版本的坑。2. 干净、可回滚的 MySQL 8 安装过程2.1 安装前的系统准备与依赖检查在敲安装命令之前先把系统仓库索引更新一遍避免因为缓存里的包信息过期导致解析不到或装到旧版本sudo apt update如果你是在一台全新云服务器上操作先看一眼磁盘剩余空间。MySQL 8 安装后数据目录加二进制文件大概会占 500MB 到 1GB空间太小容易在后续初始化时报No space left on devicedf -h /var/lib/mysql此时/var/lib/mysql大概率还不存在直接看根分区就行。还有一点容易被忽略如果系统里已经装了 MariaDB再装 MySQL 会有包冲突因为两者都提供mysql-server会提示删除现有 MariaDB 包。建议先查一下dpkg -l | grep -E mysql|mariadb有结果的话先想清楚是不是真的需要切到 MySQL 8别直接无脑装把现有数据库给顶掉了。2.2 用 apt 安装 mysql-server 的具体操作环境确认没问题后执行sudo apt install mysql-server -y-y是为了避免交互式确认。安装过程会创建系统用户mysql初始化数据目录/var/lib/mysql并注册 systemd 服务mysql.service。装完之后不要急着去建库先看服务状态sudo systemctl status mysql --no-pager正常情况下第一行应该显示active (running)。如果看到failed或者activating (auto-restart)就先用日志定位后面第 6 节我会专门讲排查路径。顺手确认一下监听端口和 socket 文件ss -lnp | grep 3306 ls -l /var/run/mysqld/mysqld.sock3306是 MySQL 默认监听端口socket 文件则用于本机进程间通信。两个都正常说明安装没有大问题。2.3 启动、停止、开机自启的正确姿势Ubuntu 上的 MySQL 服务名是mysql不是mysqld。这一点很坑因为在别的一些发行版上服务叫mysqld很多人照着网上命令敲systemctl restart mysqld系统会提示服务不存在。日常维护命令如下sudo systemctl stop mysql sudo systemctl start mysql sudo systemctl restart mysql sudo systemctl enable mysqlenable是设置开机自启。Ubuntu 的包在安装时默认就已经 enable所以通常不用手动执行。但如果你用快照恢复或者手动停止了服务最好确认一下sudo systemctl is-enabled mysql输出enabled就是正常的。这里的逻辑是把 MySQL 交给 systemd 托管一旦进程崩溃会被自动拉起日志也会归到 journald 里排查时直接用journalctl -u mysql就能看到完整历史。3. 绕开 auth_socket从 sudo mysql 到真正的密码登录3.1 为什么会出现“不用密码就进去了”装完 MySQL 后你直接运行sudo mysql会直接进入 mysql 客户端命令行不需要密码。这是因为 Ubuntu 软件源在初始化时把 root 的认证方式设成了auth_socket。简单说只要操作系统用户是 root或通过 sudo 以 root 身份就能通过本地 socket 直接认证成功密码环节被完全跳过。这不是故障而是设计。它的好处是在系统管理员未设置密码前root 不会被网络端口暴露出可登录入口。坏处也很明显任何能拿到 root 权限的系统用户都能直接操作数据库而且你没法用mysql -u root -p从远程或非 root 系统用户登录。所以正常使用前我们要把 root 改成密码认证。但要注意一点不要直接把 root 改成mysql_native_password除非你有老客户端兼容性需求否则应该保留caching_sha2_password这是 8.0 默认且更安全的认证方式。3.2 给 root 设置密码并切换到密码认证进入 mysql 命令行SELECT user, host, plugin FROM mysql.user;你会看到类似下面的数据---------------------------------------------------- | user | host | plugin | ---------------------------------------------------- | debian-sys-maint | localhost | caching_sha2_password | | mysql.infoschema | localhost | caching_sha2_password | | mysql.session | localhost | caching_sha2_password | | mysql.sys | localhost | caching_sha2_password | | root | localhost | auth_socket | ----------------------------------------------------修改 root 的认证方式和密码ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY 你的强密码; FLUSH PRIVILEGES;退出后用密码登录测试mysql -u root -p输入刚才设置的密码能进来就说明切换成功。这里有个细节如果客户端工具不支持caching_sha2_password报错后你可以临时改成mysql_native_password但只能作为过渡手段更好的方案是升级客户端驱动而不是迁就老协议。3.3 创建业务账号并限定主机日常使用不要所有应用都走 root。建一个最小权限的业务账号更稳妥比如给一个叫appdb的库建专用账号CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER appuserlocalhost IDENTIFIED BY 另一个强密码; GRANT ALL PRIVILEGES ON appdb.* TO appuserlocalhost; FLUSH PRIVILEGES;注意这里的localhost限制了只能从本机连接。如果应用在另一台机器上需要单独创建appuser192.168.1.%或appuser%的账号并把权限重复授予一遍。很多人只改了bind-address却忘了创建对应 host 的账号结果远程还是Access denied这个问题在下一节展开。4. 远程连接配置bind-address、防火墙与账号授权4.1 bind-address 改了之后重启还是连不上怎么办MySQL 默认只监听本机127.0.0.1这是由/etc/mysql/mysql.conf.d/mysqld.cnf里的配置控制的[mysqld] bind-address 127.0.0.1要让外部机器连接需要改成bind-address 0.0.0.0然后重启服务sudo systemctl restart mysql改完先用ss -lnp | grep 3306确认监听地址是否已经变成0.0.0.0:3306。如果这里显示的仍然是127.0.0.1:3306大概率是配置文件改错了位置。Ubuntu 上 MySQL 的主配置是/etc/mysql/mysql.conf.d/mysqld.cnf不是/etc/mysql/my.cnf顶部如果你把bind-address写到了[client]段或者没写到[mysqld]段下面重启后不会生效。如果监听地址已经是0.0.0.0但远程还是连不上下一步看防火墙。4.2 防火墙规则与端口确认Ubuntu 默认可能没开 ufw但云服务器一般还有安全组拦在前面。先查本地防火墙sudo ufw status如果是active放行 3306 端口sudo ufw allow from 192.168.1.0/24 to any port 3306 proto tcp这里比裸放ufw allow 3306安全得多只允许内网网段访问。如果你用的是云服务器还要记得在控制台安全组里同步放行。很多本地测试环境怎么都连不上最终发现是安全组没加规则。放行后用另一台机器测试nc -vz 服务器IP 3306如果端口通再检查账号授权。MySQL 的账号是按“用户 主机”区分的远程连接时主机匹配不上即使密码正确也会被拒绝。4.3 账号授权与常见客户端连接报错远程访问的正确姿势是给专属主机创建账号CREATE USER appuser192.168.1.% IDENTIFIED BY 密码; GRANT ALL PRIVILEGES ON appdb.* TO appuser192.168.1.%; FLUSH PRIVILEGES;如果你懒得区分可以直接用%通配所有主机但之后一定要限制这个账号的权限密度。实际项目中我建议%只用于确实需要任意来源连接的场景比如容器化应用。远程客户端连接时比较常见的报错是Access denied for user appuser...。优先顺序应当是账号是否存在、host 是否匹配、密码是否正确、权限是否授予。不要一上来就怀疑防火墙先在本机用mysql -u appuser -p -h 127.0.0.1测试同样的账号能登录就能把问题迅速缩小到网络层和授权层。5. 安装后必做的安全加固、字符集和时区5.1 启用 validate_password 组件检查密码强度MySQL 8 的密码校验从插件换成了组件名字叫validate_password。默认情况下这个组件不会自动启用我建议装上。直接在 mysql 命令行执行INSTALL COMPONENT file://component_validate_password;执行后可以验证SHOW COMPONENT;启用后新建用户时如果密码强度不够会直接报错。比如CREATE USER testlocalhost IDENTIFIED BY 123456;大概率会提示密码不满足策略。默认策略要求密码至少 8 位包含大小写、数字和特殊字符。开发环境如果觉得太严格可以把策略调低一档SET GLOBAL validate_password.policy LOW; SET GLOBAL validate_password.length 6;但注意SET GLOBAL重启后失效如果需要持久化还得在配置文件里加[mysqld] validate_password.policy LOW validate_password.length 6测试环境可以放宽生产环境我建议保持默认。这个组件不会阻碍正常业务但能在源头上防止你随手设一个root123之类的弱口令。5.2 把默认字符集和排序规则改成 utf8mb4MySQL 8 在 Ubuntu 里的默认字符集已经是utf8mb4了排序规则默认是utf8mb4_0900_ai_ci。但如果你要兼容旧的业务代码或老版本驱动0900_ai_ci可能不被识别。可以在/etc/mysql/mysql.conf.d/mysqld.cnf的[mysqld]段下显式设置character-set-server utf8mb4 collation-server utf8mb4_unicode_ci重启后查看SHOW VARIABLES LIKE character_set_server; SHOW VARIABLES LIKE collation_server;有个经验值得记一下建库、建表时最好显式声明字符集不要完全依赖全局配置。因为如果一个库早期的表用的utf8mb3你只改全局配置也不会自动迁移旧表。正确的迁移姿势是ALTER TABLE加CONVERT TO CHARACTER SET utf8mb4这一步对线上大表要挑业务低峰做。5.3 时区配置和连接层时区问题MySQL 的时区默认跟随系统时区大多数情况下不用管。但如果你发现程序里存的时间比本地时间早了 8 小时说明 MySQL 把时间当作 UTC 处理。最省事的解决方式是在配置文件里写default-time-zonedefault-time-zone 08:00这里有个坑如果你写成default-time-zone Asia/Shanghai而 MySQL 还没加载时区表启动可能直接失败或者客户端访问时报错。最好用固定偏移量08:00不用加载时区表通用性也更强。改完重启服务后让业务方看一条SELECT NOW();的输出是否和本地时间一致。5.4 目录权限与网上流传的 777网上有一类教程遇到权限类报错就让chmod -R 777 /var/lib/mysql。这是很危险的操作等于把整个 MySQL 数据目录向系统所有用户开放。正常情况下/var/lib/mysql的数据目录属主和属组都是mysql:mysql权限是750或700ls -ld /var/lib/mysql如果看到权限异常最稳妥的做法是恢复属主和基础权限而不是给 777sudo chown -R mysql:mysql /var/lib/mysql sudo chmod -R 750 /var/lib/mysql同理备份目录、日志目录也不建议给 777。MySQL 跑不起来时权限问题只是冰山一角真正的原因往往在日志里把时间花在排查原因上比粗暴改权限更值。6. 高频故障排查连不上、起不来、开机报错6.1 socket 连接失败常见原因新手最常碰到的报错长这样ERROR 2002 (HY000): Cant connect to local MySQL server through socket /var/run/mysqld/mysqld.sock (2)这个报错的第一层意思很直白客户端找不到 socket 文件通常说明 MySQL 服务没起来。先看sudo systemctl status mysql --no-pager如果服务是failed状态看日志sudo journalctl -u mysql -n 50 --no-pager另一个常见原因是/var/run/mysqld目录被误删或权限被改。因为/var/run是 tmpfs重启后目录会重建如果手动调整过权限可能导致 mysqld 无法创建 socket。修复办法sudo mkdir -p /var/run/mysqld sudo chown mysql:mysql /var/run/mysqld然后再启动服务。还有一个偏门原因本机客户端指定了错误配置。mysql客户端会读取/etc/mysql/my.cnf里的socket路径如果你改过配置客户端连的 socket 和服务器实际监听的 socket 不一致也会报同样错误。这时候可以用mysql --socket/var/run/mysqld/mysqld.sock指定路径测试。6.2 Access denied 的排查顺序Access denied是另一类高频报错。它一般出现在密码错误、账号不存在、host 不匹配、权限没刷新这四种情况里。排查顺序应该从“账号确实存在吗”开始SELECT user, host, plugin FROM mysql.user;确认账号存在后再确认你登录时用的主机匹配规则。比如你从192.168.1.50连过来但只建了applocalhost那必然会被拒绝。此时要建app192.168.1.%或app%。如果账号和 host 都对还是报Access denied看是不是密码里包含特殊字符在命令行里被 shell 转义了。最后再考虑是否执行过FLUSH PRIVILEGES——其实GRANT之后不需要 flush但如果你直接往mysql.user表里 INSERT 了记录那必须 flush 才能让权限缓存生效。6.3 开机报 failed to start gdb service和 MySQL 有关系吗有些人在 Ubuntu 24.04 开机时看到类似这样的报错Failed to start gdb service.这个服务名和 MySQL 完全没有关系但因为它出现时机和 MySQL 启动时间接近经常被误判成数据库坏了。遇到这种“系统层面开机报错”的情况正确的做法是先定位具体 unitsudo systemctl status gdb.service --no-pager sudo journalctl -u gdb.service -n 30 --no-pager在我遇到的情况里这个报错往往来自某个残留的异常 unit 或依赖关系而不是 MySQL 本身。排查时一定要先区分是mysql.service报错还是其他服务报错。看 MySQL 的独立状态和独立日志比在一堆开机输出里猜要高效得多。把两个服务的systemctl status输出对比一下几分钟就能排除干扰。6.4 看日志的正确方式Ubuntu 20.04 之后MySQL 的日志已经交给 journald 统一管理但错误日志仍在/var/log/mysql/error.log。排查问题时的组合命令是sudo tail -n 100 /var/log/mysql/error.log sudo journalctl -u mysql --since today -n 100 --no-pager注意区分error.log更适合看 MySQL 服务内部错误比如 InnoDB 恢复、权限问题、表损坏journalctl更适合看 service 启动流程比如配置加载顺序、systemd 设置、退出码。两个都看一眼基本能把问题定位到具体模块。如果日志文件长时间没有写入先看磁盘df -hMySQL 在数据磁盘写满时会拒绝启动错误日志里的典型提示是Disk is full。这种情况下扩容或清理旧备份才是正道光重启服务没有用。7. 日常维护备份、日志轮转与升级注意7.1 mysqldump 备份与恢复MySQL 8 自带mysqldump适合中小规模的逻辑备份。我最常用的备份命令sudo mysqldump -u root -p --single-transaction --routines --triggers --all-databases /backup/mysql_full_$(date %F).sql--single-transaction对 InnoDB 表可以做到不锁表备份导出过程中业务还能正常写入。--routines和--triggers会把存储过程、触发器等对象一起备份不加这两个参数容易漏。恢复测试也要定期做别备份完就扔在那里mysql -u root -p /backup/mysql_full_2025-01-01.sql注意恢复前要确认目标库已经清空否则重复导入会报数据重复或主键冲突。7.2 日志轮转与错误日志维护Ubuntu 的 MySQL 包自带 logrotate 配置文件在/etc/logrotate.d/mysql。它会轮转/var/log/mysql/error.log保留一定数量的历史文件避免日志无限制增长撑满磁盘。你可以检查一下自己的配置是否被改过cat /etc/logrotate.d/mysql如果你把错误日志路径换到了别的地方一定记得同步修改 logrotate 配置。否则 MySQL 依然往旧路径写日志而日志文件永不分隔最终变成几十 GB 的巨型文件定位问题时会非常痛苦。7.3 小版本升级与 apt-mark holdUbuntu 仓库的 MySQL 8.0 会跟随系统安全更新偶尔会有小版本升级。正常情况下sudo apt update sudo apt upgrade会顺带升级 MySQL。升级前强烈建议先做一次全量备份并在测试环境验证兼容性。尤其要注意如果以后官方仓库推送的版本从 8.0 跳到 8.4哪怕命令一样升级路径也不一定能原地完成。如果你不想让 MySQL 被意外升级可以把它设为 hold 状态sudo apt-mark hold mysql-server mysql-client需要升级时再取消 hold。对于生产环境我倾向于把数据库的升级节奏单独掌控不完全跟着系统包走。最后一个实际操作心得MySQL 8 在 Ubuntu 24.04 上跑起来并不难难点永远在初始化之后的那几步——认证方式、远程授权、字符集、时区、权限收敛。建议你装好后把这篇文章里的检查项逐个跑一遍尤其是bind-address和账号 host 这两件事提前确认好后面能省掉很多来回折腾的时间。
返回列表