☰
Ubuntu 22.04安装MySQL 8.0完整指南:从root认证到远程连接踩坑记录
2026/10/13 4:13:23 网站建设 项目流程

装 MySQL 这事,听起来简单,但我在 Ubuntu 22.04 上栽过好几次跟头。尤其是刚上手时,装完发现 root 密码不生效、服务起不来、字符集还是 latin1,每次都要折腾半天。后来把整个流程从头到尾捋了一遍,才搞清楚 Ubuntu 22.04 默认的 MySQL 8.0 和以前 CentOS 上那套玩法有不少区别。这篇我就把从零开始到能正常用起来的完整过程写清楚,包含每个步骤背后的原因,以及我踩过的坑。

这篇内容适合刚接触 Linux 和 MySQL 的人照着抄,也适合已经装上但连不上的同学排查问题。核心流程是:检查环境、用 apt 安装、初始化安全配置、调整编码和访问权限、最后把常见问题一次性说透。

1. 开装之前:系统版本、软件源和安装方式怎么选

1.1 先确认系统版本和权限

别一上来就敲apt install mysql-server,先花两分钟确认下系统环境和权限,能省掉后面一堆莫名其妙的问题。

# 查看 Ubuntu 版本 lsb_release -a # 查看系统架构 uname -m # 确认当前用户是否有 sudo 权限 sudo -l

Ubuntu 22.04 的官方软件源里自带的就是 MySQL 8.0 系列(目前是 8.0.x 的小版本更新),这个版本和 5.7 相比,在认证插件、默认字符集、SQL 模式上都有明显变化。你如果之前只玩过 5.7,请把心态归零。

权限方面,安装 MySQL 必须有 root 权限,我是用 sudo 操作的,整个教程基于 sudo 模式。如果你的账号不在 sudo 组里,先解决这个前置问题。

1.2 我为什么推荐直接用官方源而不是第三方仓库

很多人一搜教程,会看到让你添加 MySQL 官方 apt 仓库或第三方 PPA 再安装。我的建议是:除非你有特别明确的新功能需求,否则直接用 Ubuntu 官方源自带的 mysql-server 就够了。

原因有三点。第一,官方源的包和系统库依赖匹配度最高,apt install会自动处理好依赖关系,几乎不会有缺 lib 的问题。第二,安全补丁通过系统自带的apt update && apt upgrade就能统一更新,不需要记另外一套维护路径。第三,第三方仓库偶尔会出现和当前系统 glibc 不兼容的情况,装到一半报错特别折腾。

我见过同事装了某 PPA 的 MySQL 8.0.34,结果apt upgrade时把 libaio 版本升级了,MySQL 起不来,最后只能卸载重装。这类问题用官方源基本碰不到。

当然,如果你需要非常新的补丁版本,或者想用 MySQL 官方仓库里的一些特殊优化包,那另说。对 90% 的业务场景,系统源版本完全够用。

1.3 先更新软件索引,但别乱升级系统包

安装前执行更新是必要的,但要注意范围和力度。

# 更新软件包索引 sudo apt update

这一步会把软件源里的包列表刷新,让 apt 知道当前有哪些版本可用。我建议安装前做一次,避免本地缓存里还是旧的索引导致装到旧版本。

至于要不要顺手sudo apt upgrade,我的习惯是只在全新环境或者明确知道系统包没有大版本变更时才做。生产环境或正在跑的机器,不要在这个时候升级内核、systemd 之类的大件,防止重启后服务起不来。装个 MySQL 而已,没必要承担系统升级的风险。

2. 安装和初始化:从 apt install 到 mysql_secure_installation

2.1 安装 mysql-server 并验证基础状态

接下来正式安装。这一步没什么花头,但要注意包名是mysql-server,不是mysql或者mysql-client。mysql这个元包在 Ubuntu 上很多时候是虚拟包,指向 MariaDB 或 MySQL 客户端,直接装它可能装出跟你预期不一样的数据库。

# 安装 MySQL 服务端(会自动带上客户端) sudo apt install mysql-server -y # 安装完成后检查版本 mysql --version # 查看 mysql 服务的 systemd 状态 systemctl status mysql

安装完不需要手动 start,Debian/Ubuntu 系的包在安装完成后会自动把服务拉起来并设置开机自启。你用systemctl status mysql应该能看到active (running)。这里服务名是mysql,不是mysqld,很多习惯 CentOS 的人会敲systemctl start mysqld然后发现没有这个服务,这个要注意。

如果状态不是 running,先别急着往下走,看下错误日志:

sudo tail -100 /var/log/mysql/error.log

日志文件不存在就说明 MySQL 压根没初始化成功,通常是数据目录权限或磁盘空间问题。排障细节我会放到后面的问题章节详细说。

2.2 你可能不知道:默认 root 用的是 auth_socket 免密登录

安装完成后,你直接用mysql -u root -p输入密码,会发现自己压根没设过密码,登录失败。这时候别慌,Ubuntu 上 MySQL 8.0 默认创建的 root 账号,认证插件是auth_socket,并不是常见的密码认证。

auth_socket的机制是:只要操作系统用户是 root(或者 sudo 到 root),通过本地 socket 连接时,MySQL 直接认为你就是 root,不再额外验证密码。这样设计的好处是系统 root 权限本身已经是最高的了,MySQL root 就不需要再暴露一个密码给对方,降低了密码泄露和暴力破解的风险。

所以安装完成后,正确的本地登录方式是:

sudo mysql

不需要加-u root也不需要密码,直接进 MySQL 命令行。进去后可以验证一下认证插件:

SELECT user, host, plugin FROM mysql.user WHERE user = 'root';

你会看到 root 对应的 plugin 是auth_socket。这是 Ubuntu 默认行为,不是 bug,更不是没设置好。

2.3 mysql_secure_installation 初始化安全配置

接下来要做安全初始化,运行:

sudo mysql_secure_installation

这个交互式脚本会依次问几个问题,我一个个说我的建议和踩坑经验。

第一步:密码强度校验插件。它会问你是否安装 VALIDATE PASSWORD COMPONENT。如果你用 root 密码登录并且这台机器暴露在公网,建议安装;如果只是内网开发环境,可以跳过。注意一件事:组件安装后,你设置的密码必须满足对应强度策略(LOW/MEDIUM/STRONG),不符合会直接拒绝。我一般开发机上选跳过,生产机选 MEDIUM。

第二步:设置 root 密码。这里的 root 密码,管的是通过 TCP/IP 连接时的密码认证。但前面说了,默认 root 走的是 auth_socket,本地 sudo mysql 依然免密。很多人在这里设置了密码,退出后敲mysql -u root -p输密码,发现还是报错,就蒙了。原因是:当你用-p走 TCP 或 socket 密码认证时,MySQL 会检查 root 的 plugin;如果 plugin 还是 auth_socket,密码认证就是不生效的。关于怎么把 root 改成密码登录,我在 2.4 单独说。

第三步:是否移除匿名用户。选y,生产环境必须删,开发环境也建议删。匿名用户是历史遗留问题,留着容易让本机其他低权限用户无密码连进数据库。

第四步:是否禁止 root 远程登录。选y,默认必须禁止。实际业务中一般建议新建专用账号给远程连接,而不是直接放开 root。如果后面开发需要 root 远程,而是应该创建用户并配置权限,而不是改 root。

第五步:是否删除 test 数据库。选y。系统默认自带一个任何人都能访问的 test 库,留着意义不大。删除后不会有任何影响。

第六步:是否立即重载权限表。选y,让刚才的变更生效。

全部答完,脚本会提示 finished。到这里安装和初始化才算真正完成。

2.4 root 的密码认证到底怎么切

如果你后续需要通过 Navicat、DBeaver 这类图形客户端用 root 连接,就必须把 root 从 auth_socket 切到caching_sha2_password。

sudo mysql ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '你的新密码'; FLUSH PRIVILEGES;

执行完后再试:

mysql -u root -p

输入刚才的密码,应该就能登进去。切到密码认证后,本地sudo mysql依然可用吗?实测依然可用,因为 auth_socket 只是换了,MySQL 8 对 root@localhost 的逻辑是:如果通过 socket 以系统 root 身份连接,优先匹配 auth_socket 规则,密码认证作为补充。这里不用细究,记住切完之后本地和远程都能登录就行。

安全提示一句:如果机器有公网 IP,不建议用 root 远程连接,最好新建一个业务账号。生产环境真的不要图省事,root 一旦被爆破,整个库就没了。

3. 配置调整:字符集、时区、远程访问一次到位

3.1 先搞清楚配置文件怎么组织

MySQL 8.0 在 Ubuntu 上的配置文件分散在多个位置,初看会觉得乱,其实加载顺序是固定的:

  • /etc/mysql/my.cnf是总入口,里面用!includedir引入了多个目录
  • /etc/mysql/conf.d/放全局配置片段
  • /etc/mysql/mysql.conf.d/放 mysqld 服务端专属配置片段

重点看/etc/mysql/mysql.conf.d/mysqld.cnf,服务端核心参数都在这里。改配置的正确姿势是:

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf # 修改后手动重启 sudo systemctl restart mysql

不要乱动/etc/mysql/my.cnf根文件,它本身只是目录入口,改错容易出问题。

3.2 字符集:Ubuntu 22.04 默认就是 utf8mb4,但还要确认

很多人刚装完用建表时,发现表字符集是 latin1,就到处找教程改。其实 MySQL 8.0 的默认字符集已经是utf8mb4,但character_set_server和collation_server的默认值在编译时可能被覆盖,我用源码编译时深有体会。为了确保无误,安装后可以改一下配置:

[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_0900_ai_ci

为什么用utf8mb4_0900_ai_ci?这是 MySQL 8.0 引入的 Unicode 9.0 排序规则,支持更多字符、排序更准确。如果你的业务数据库是从 5.7 迁过来的,原来用的是utf8mb4_unicode_ci,两者在排序结果上有细微差别,导入数据后可能影响查询排序、唯一索引判断。历史项目建议保持原排序规则,新项目直接0900_ai_ci就行。

改完重启:

sudo systemctl restart mysql

验证:

SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';

重点看character_set_server是否已变成 utf8mb4。

注意:配置文件里的编码只管服务端新建库和表的默认值。如果你库里已经建好表了,单独改服务端参数不会改变已有表的字符集,需要ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4;逐个转换,转换前记得先备份。

3.3 远程连接:bind-address、账号授权、防火墙一个不能少

这是教程里被问最多的问题。装好了本机能连,客户端连不上,十有八九是下面三件事没做全。

第一步:改 bind-address。默认情况下 mysqld 只监听 127.0.0.1,外部 IP 根本连不上 socket。在 mysqld.cnf 里找到:

bind-address = 127.0.0.1

改成:

bind-address = 0.0.0.0

0.0.0.0表示监听所有 IPv4 地址。改完重启 mysql。这里注意,如果机器是直接暴露在公网的,建议改成具体的局域网 IP,或者干脆用防火墙限制来源,而不是无脑 0.0.0.0。

第二步:创建远程登录的用户。MySQL 的用户由用户名@主机两部分组成,'root'@'localhost'和'root'@'%'是两个独立账号。

-- 创建远程账号,密码按你的策略来 CREATE USER 'app_user'@'%' IDENTIFIED BY 'StrongPassword123!'; -- 授权,建议按库授权,不要一把梭给 ALL GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'%'; -- 如果你有从库复制之类的需求才需要给全局权限,否则尽量最小化 FLUSH PRIVILEGES;

'%'表示任意主机。安全起见,如果你的客户端 IP 是固定的,比如公司的出口 IP,写成'app_user'@'192.168.1.0/255.255.255.0'或者具体的 IP,会更稳妥。

第三步:检查防火墙。Ubuntu 22.04 默认可能没开 ufw,但云服务器厂商的安全组是默认挡在系统之外的。系统内执行:

sudo ufw allow 3306/tcp

云服务器的话,去安全组规则里放行 3306。这一步很多人漏了,客户端 telnet IP 3306 不通,问题不在 MySQL,而是安全组。

全部配置完,用客户端工具连接测试。如果还报错Access denied,大概率是授权问题,把创建用户和授权的 SQL 重新执行一遍;如果报Authentication plugin相关错误,看第 5 章的兼容性说明。

3.4 时区设置:做了不亏

MySQL 的CURRENT_TIMESTAMP默认取系统时区。Ubuntu 服务器时区如果不是 UTC,那 MySQL 的 NOW() 会因为系统时区和数据库时区不一致而偏差。我的建议是直接在配置里写明确:

[mysqld] default-time-zone = '+08:00'

如果你不想硬编码成东八区,也可以把系统时区设置好,然后 MySQL 用动态方式:

SET GLOBAL time_zone = '+08:00';

但重启会丢,所以还是写进配置文件更持久。这个配置对后续避免日志时间、业务时间对不上特别有帮助。

4. 日常使用与常用操作:服务管理、建库建号、备份

4.1 systemd 服务管理速查

MySQL 装好后,日常维护用的命令其实很少,我列一下我每天用到的:

# 查看状态 sudo systemctl status mysql # 重启服务 sudo systemctl restart mysql # 停止服务 sudo systemctl stop mysql # 开机自启(默认已开启,确认一下) sudo systemctl enable mysql # 实时查看日志 sudo journalctl -u mysql -f

日志是排障第一手资料。MySQL 自身的错误日志位置在/var/log/mysql/error.log,如果 service 完全启动不了,优先看它。

一个容易被忽略的点:改完配置后用systemctl restart mysql卡住很久,或者直接失败,检查是不是 SQL 模式配置写错或端口被占用。这类问题别急着反复 restart,先systemctl status看具体报错。

4.2 新建业务库和账号的完整套路

项目上线前,建库、建用户、授权是基本操作。我给一个规范流程,你可以直接抄:

-- 建库,指定字符集,避免继承全局默认值导致的意外 CREATE DATABASE IF NOT EXISTS app_db DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_0900_ai_ci; -- 建账号,密码强度按内网策略 CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'YourAppPass123!'; CREATE USER 'app_user'@'%' IDENTIFIED BY 'YourAppPass123!'; -- 授权:应用账号只需要自己库的权限,不要给全局权限 GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP ON app_db.* TO 'app_user'@'localhost'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP ON app_db.* TO 'app_user'@'%'; FLUSH PRIVILEGES;

生产环境我建议:除非必要,不然app_user不给 DROP、ALTER 权限,防止误操作。运维账号可以单独建一个ops_user,给需要的库授予ALL PRIVILEGES,但也不建议给GRANT OPTION,避免权限被二次分发。

4.3 备份别嫌早:mysqldump 一学就会

备份是所有 DBA 的底线,不备份等于把自己架在火上烤。最简单的逻辑备份用 mysqldump:

# 备份整个库 mysqldump -u root -p --single-transaction --routines --triggers app_db > app_db_$(date +%F).sql # 恢复 mysql -u root -p app_db < app_db_20250101.sql

--single-transaction很关键,对 InnoDB 表做一致性快照,不会锁表影响线上业务。--routines --triggers备份存储过程和触发器,很多人漏掉,恢复后才发现函数没了。

如果你用 root 备份,记得备份完及时把密码从 shell history 里清掉,或者改用配置文件里写[client]密码的方式,防止密码泄露到日志。

5. 常见问题与排查实录:都是你大概率会遇到的事

5.1 忘了 root 密码怎么办

这个场景几乎每个人都遇到。在 Ubuntu 22.04 上,由于默认 root 是 auth_socket,你其实不需要密码就能进:

sudo mysql

然后直接改密码:

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '新密码';

如果你之前已经把 root 改成密码认证,又忘了密码,那就得用跳过授权表的方式来重置。步骤如下:

# 停掉 MySQL sudo systemctl stop mysql # 以跳过授权表的方式启动 sudo mysqld_safe --skip-grant-tables --skip-networking &

用--skip-networking是防止在免密状态下被外部连接,只允许本机 socket 操作。然后:

sudo mysql -u root FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '新密码'; FLUSH PRIVILEGES;

最后重启服务:

sudo pkill mysqld_safe sudo systemctl start mysql

提醒:--skip-grant-tables模式下 MySQL 不校验任何账号密码,误操作风险极高,整个过程不要让数据库处于未保护状态太久,操作完立刻恢复正常启动。

5.2 MySQL 服务起不来

systemctl start mysql失败,先从这五个方向排查。

1. 磁盘空间是否满了。df -h看下/var/lib/mysql所在分区。磁盘满时 MySQL 会拒绝写入并崩溃,错误日志里通常有 Disk full 或 No space left。清理磁盘后重启即可。

2. 数据目录权限是否被改过。MySQL 对数据目录/var/lib/mysql的属主要求是mysql:mysql。如果之前用 root 操作过数据目录,或者从其他地方拷贝了数据文件,很容易出现权限错乱。修复:

sudo chown -R mysql:mysql /var/lib/mysql sudo chmod 750 /var/lib/mysql

3. 端口是否被占用。ss -lntp | grep 3306,看是否有其他进程占用了 3306。常见的是系统装了 MariaDB 或者另一个 MySQL 实例。要么关掉另一个,要么改端口。

4. 配置文件语法错误。改完 mysqld.cnf 后起不来,大概率是参数写错或值不合法。比如innodb_buffer_pool_size写成了 1G 少了单位、sql_mode里加了不存在的模式,都会导致启动中断。用mysqld --validate-config可以提前检查配置。

sudo mysqld --validate-config

5. InnoDB 崩溃恢复失败。非正常断电后偶尔会出现。错误日志里看到InnoDB: Corruption或cannot recover,说明数据页损坏。先尝试从备份恢复,不要盲目执行innodb_force_recovery,那个是最后手段,只能尽量捞数据。

5.3 客户端连不上:MySQL 8 的认证插件兼容性

用老版本的客户端工具连接 MySQL 8 时报错:

Authentication plugin 'caching_sha2_password' cannot be loaded

这个报错在 2018 年 MySQL 8 刚出来时高频出现,现在的开发工具基本都支持了,但如果你还在用 Python 的旧版 mysqlclient、PHP 5.x 或者 JDBC 驱动版本过老,就会碰到。解决方案就几个:

  • 升级客户端驱动/软件到最新版,比如 JDBC 用 8.0.33 以上
  • 如果是老项目没法升,给用户改成 mysql_native_password:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY '密码'; FLUSH PRIVILEGES;

mysql_native_password是 5.7 时代的认证插件,MySQL 8 默认不推荐,但为了兼容老应用可以保留。能升级尽量升级,不要长期依赖这个插件。

5.4 数据库能连上,但执行 SQL 报乱码

建库的时候没指定字符集,数据库继承的还是默认的 utf8mb4,但建表时用了 latin1 或库是旧版本迁过来的,就容易乱码。排查顺序:

-- 看服务端 SHOW VARIABLES LIKE 'character_set_server'; -- 看库 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'app_db'; -- 看表 SHOW TABLE STATUS FROM app_db LIKE 'your_table';

如果库里已经有表,先备份,再转换:

ALTER TABLE app_db.your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

乱码问题麻烦在于数据一旦以错误的编码写入,转换也很难恢复完整。所以最有效的办法是建库、建表、连接串三层全指定 utf8mb4,连接时也记得加characterEncoding=utf8(JDBC)或charset=utf8mb4(连接串),不要依赖服务端默认值。

5.5 小技巧:让 systemd 输出更清晰

排查系统问题的时候,systemctl status mysql显示的信息有时候不够细。我习惯完整截图跑一遍:

sudo systemctl stop mysql sudo systemctl start mysql sudo systemctl status mysql --no-pager sudo journalctl -u mysql --since "5 minutes ago" --no-pager

后两条命令能帮你匹配到具体报错点。大多数人在这一步就能定位到上面前五个问题中的一个。

最后分享点个人经验

装 MySQL 真正花时间的往往不是安装本身,而是对默认行为的理解。Ubuntu 22.04 上 auth_socket 默认认证、utf8mb4 默认字符集、systemd 服务管理这三件事搞明白,后面的使用会非常顺畅。

我现在装新环境的固定动作是:装完先确认版本,然后 mysql_secure_installation 初始化,接着改字符集、时区、bind-address,最后建业务库和专用账号,再做一次备份测试。整套流程下来不到二十分钟。如果你按照这里面的步骤操作,大概率能一次成功。万一还是有问题,把错误日志里的最后几条贴出来,对着问题清单一条条过,基本都能解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询