很多朋友一上来就直接apt install mysql-server或者yum install mysql-server,装完以后发现服务起不来、密码不知道、远程连不上,然后开始满世界搜错误日志。其实 Linux 装 MySQL 本身不难,难点在于不同发行版的初始化机制、权限模型、默认配置差异太大,同一个错误在两个系统里可能是完全不同的原因。这篇文章我就按自己的实际操作习惯,把从零开始装 MySQL 到能正常用起来的完整过程理一遍,包括每条命令为什么要这么写、装完以后哪些配置必须动、哪些坑几乎人人都会踩。
我默认你手里是一台干净的 Linux 服务器,可能是 Ubuntu、Debian 这类 apt 系,也可能是 CentOS、Rocky Linux 这类 yum/dnf 系。两种我都写,因为命令差异很大,混着用必出问题。
1. 装之前先想清楚:你需要的 MySQL 是哪一种
1.1 不同发行版自带的 MySQL 版本差异很大
Linux 系统自带的软件源里一般都有 MySQL 相关的包,但版本和实现方式各有不同。Ubuntu 22.04 的源里是 MySQL 8.0.x,Debian 12 同样也是 8.0;CentOS 7 默认源里已经找不到 MySQL,替代品是 MariaDB;CentOS Stream 9 / Rocky Linux 9 的 AppStream 里带的是 MySQL 8.0 和 MariaDB 10.5。这里有个很常见的误解:很多人以为yum install mysql-server装的是 MySQL,其实 CentOS 7 里这个命令大概率会装成 MariaDB。MariaDB 虽然兼容 MySQL 的大部分功能,但如果你在跑一些依赖 MySQL 专有特性的业务,或者要严格对应生产环境的 MySQL 版本,那还是会踩到差异。
所以在动手前,第一件事不是敲安装命令,而是确认你想要的 MySQL 版本,以及当前系统源里到底有什么。我一般先跑cat /etc/os-release看发行版,再跑apt list --upgradable 2>/dev/null | grep -i mysql或yum list available | grep -i mysql确认可用版本。如果系统源版本不合要求,再考虑配置 MySQL 官方仓库。
1.2 安装方式选哪种:系统源、官方仓库、还是编译安装
网上教程很多,路线也很乱,我把常见安装方式拉平对比一下,方便你根据场景选。
| 安装方式 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 系统自带源安装 | 命令短、依赖自动解决、与系统集成好 | 版本可能偏旧、不是官方最新 | 学习、测试、非关键业务 |
| 官方 Yum/Apt 仓库安装 | 版本官方可控、可以锁版本、升级方便 | 需要配仓库和 GPG 密钥、源在国外可能慢 | 生产环境、需要特定版本 |
| 二进制 tar 包安装 | 完全可控、不干扰系统包管理 | 初始化、systemd 服务、升级都要手动管 | 定制化部署、离线环境 |
| Docker 容器部署 | 环境隔离、版本切换快、数据卷管理 | 数据持久化要自己处理、性能略损耗 | 本地开发、微服务架构 |
我个人的建议:第一次练手或者做小项目,直接用系统源装,先把整个流程跑通。生产服务器,用官方仓库装且锁定版本。二进制包的灵活度最高,但手动管理的东西太多,不太适合新手一上来就搞。Docker 那条路线适合已经对 MySQL 有基本认识的场景,而且容器内外端口、数据卷的权限问题也会分散你的注意力。
1.3 装之前的环境检查清单
在我实际操作中,下面几项检查能避免后面一半以上的问题:
- 确认系统架构:
uname -m,x86_64 和 aarch64 的包不一样,在官方仓库下载时要选对。 - 确认系统内存:MySQL 8.0 装完冷启动就占 300-500MB 内存很正常,如果你在用 1G 内存的小机器,后面必须调低
innodb_buffer_pool_size,否则内存直接被打满然后 OOM。 - 确认端口占用:
ss -lntp | grep 3306,如果有别的实例占着 3306,后面启动会冲突。 - 确认磁盘空间:
df -h /var/lib/mysql,MySQL 的数据目录默认在这里,空间不够的话初始化就会失败。
2. 环境准备与仓库配置:为安装铺平道路
2.1 apt 系安装前的准备工作
我这里以 Ubuntu 22.04 为例。系统自带的源安装 MySQL 是非常简单的,但先做一个很关键的动作:更新软件源缓存。
sudo apt update有的精简镜像或云主机没有装gnupg、wget、curl这些基础工具,后续如果配官方源会用到,建议先检查一遍:
which gnupg wget curl如果哪个没装,就sudo apt install -y gnupg wget curl。这不是废话,我确实遇到过一台最小化安装的 Ubuntu,连curl都没有,配仓库时卡了半天。
如果你要用 MySQL 官方仓库装指定版本,流程是这样的。先去 MySQL 官方 Yum/Apt 仓库页面找到对应发行版和版本号的 deb 包地址,然后:
cd /tmp wget https://repo.mysql.com/mysql-apt-config_0.8.24-1_all.deb sudo dpkg -i mysql-apt-config_0.8.24-1_all.deb这个 deb 包的作用是帮你把 MySQL 官方仓库写入 apt 源列表,同时会把 MySQL 的 GPG 公钥导入系统。执行过程中会出现一个交互界面,让你选择要装 MySQL 的哪个版本,选好保存退出后,再更新一次源:
sudo apt update此时apt-cache policy mysql-server就能看到官方仓库里的版本了。官方仓库的好处是你可以装到比系统源更新的小版本,而且后续可以apt upgrade统一升级。缺点就是服务器在国内的话下载速度有时候不太乐观,这个可以后面换镜像源解决。
2.2 yum/dnf 系安装前的准备工作
以 Rocky Linux 9 为例,系统 AppStream 里已经带了 MySQL 8.0,只需要:
sudo dnf install -y mysql-server但如果你要装 MySQL 官方仓库的版本,和 apt 系思路类似。先导入官方仓库 rpm 包:
sudo dnf install -y https://repo.mysql.com/mysql80-community-release-el9-4.rpm这个 rpm 包会把 MySQL 官方仓库写入 dnf 源,并自动导入 GPG 公钥。然后确认仓库已生效:
dnf repolist | grep mysql此时可以看到mysql80-community之类的仓库名。安装命令:
sudo dnf install -y mysql-community-server注意 CentOS 7 的处理方式不太一样,因为默认源里根本没有 MySQL,直接yum install mysql-server的结果是 MariaDB,所以如果你真的要用 MySQL,在 CentOS 7 上必须走官方仓库。
2.3 仓库安装好后的第一个验证动作
无论哪种方式,装完以后先验证一下实际的包来源和版本:
mysqld --version正常会输出类似mysqld Ver 8.0.36 for Linux on x86_64 (...)的信息。如果你看到的是mariadb的字样,那就说明你装的是 MariaDB 而不是 MySQL,这时就要回头检查仓库配置了。
3. 核心安装实操:两条路线手把手走一遍
3.1 Ubuntu/Debian 系安装与初始化细节
系统源直接装:
sudo apt install -y mysql-server这条命令装完,MySQL 服务默认会自动启动。验证一下:
systemctl status mysql如果显示active (running),说明服务已经起来了。这一步和 CentOS 有个很大的不同:Ubuntu 上 MySQL 默认 root 用户用的是auth_socket插件认证,也就是说你不需要密码,直接sudo mysql就能进。这是很多新手被卡住的地方,习惯性以为 root 一定需要密码,结果mysql -u root -p怎么试都进不去,其实直接sudo mysql就行。
进入 MySQL 后,可以立即查看当前的认证方式:
SELECT user, host, plugin FROM mysql.user WHERE user='root';你会看到 root 用户的 plugin 是auth_socket。这种设计的好处是本地 root 登录安全性很高,坏处是你的程序想用 root 账号连接数据库时会发现连不上,因为程序没有系统 root 身份。这时就需要把 root 改成密码认证,或者新建一个专用账号。改密码认证的命令:
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '你的强密码';改完以后,mysql -u root -p就可以用密码登录了。但我不建议业务连接用 root 账号,后面我会单独说怎么建一个权限最小化的业务账号。
3.2 CentOS/Rocky Linux 系安装与初始化细节
在 Rocky Linux 9 上装系统源版本:
sudo dnf install -y mysql-server和 Ubuntu 不一样的是,这里装完以后服务不会自动启动,需要手动操作:
sudo systemctl start mysqld sudo systemctl enable mysqldenable是设置开机自启,很多人装完只 start 不 enable,服务器一重启 MySQL 就不见了,然后怀疑是程序有问题,其实只是没设自启。
启动以后,CentOS/RHEL 系的 MySQL 8.0 默认会做一次数据目录初始化,并且生成一个临时 root 密码,记录在日志里:
sudo grep 'temporary password' /var/log/mysqld.log输出类似:
[Note] A temporary password is generated for root@localhost: xxxxxx这个临时密码必须拿来首次登录用:
mysql -u root -p输入临时密码后,MySQL 会强制要求你修改密码,而且默认开启了密码复杂度校验插件,新密码必须满足一定长度和字符组合要求。如果你只是想本地测试,又不想被密码策略折磨,可以先降低策略等级:
SET GLOBAL validate_password.policy = LOW;注意 MySQL 8.0 里这个变量的路径是validate_password.policy,老版本的写法是validate_password_policy。这两个东西不一样,网上老教程一大半都在用旧写法,在 8.0 上会直接报错。
3.3 一些离线和内网环境下的特殊处理
有的服务器在内网环境,没办法访问外网仓库。这种情况下,官方 rpm 包或者 deb 包都下不进来,我碰到过几次。处理办法有两种:
第一种,在有网的机器上下载对应的 rpm/deb 包,再手动拷贝到内网机器。比如在 Rocky 上,可以用dnf download mysql-server拿到相关的 rpm 包,然后dnf install ./mysql-*.rpm离线安装。注意依赖问题,可能还要下载 libaio、ncurses 这些依赖包,比较麻烦。
第二种,直接用官方提供的二进制 tar 包。这种方式不依赖系统包管理,很适合离线环境。解压以后把目录改名为/usr/local/mysql,然后手动初始化数据目录:
cd /usr/local/mysql sudo bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data初始化日志里同样有临时密码。这种方式没有自动生成 systemd 服务,需要自己写一个 service 文件,所以我不建议新手在不需要的情况下主动选这条路。
4. 初始化配置与安全加固:装完只是开始
4.1 必做的安全初始化操作
MySQL 8.0 自带一个安全初始化脚本,名字叫mysql_secure_installation,强烈建议跑一遍。这个脚本会引导你做下面几件事:
- 设置 root 密码
- 删除匿名用户
- 禁止 root 远程登录
- 删除 test 测试数据库
- 重新加载权限表
在 Ubuntu 上跑:
sudo mysql_secure_installation在 CentOS 上跑需要先用临时密码登录改完 root 密码后再跑。脚本会先问你当前 root 密码,然后依次交互。这个脚本我每次装完都会执行,因为匿名用户和 test 库是实际攻击面,默认带着它们就是给入侵留后门。
4.2 修改字符集和排序规则
MySQL 8.0 的默认字符集是 utf8mb4,这在绝大多数场景下已经够用,所以很多新项目直接用默认值就行。但有一点要注意:如果你是从 MySQL 5.7 升级过来的,或者数据库里已经有老数据,务必确认连接层和应用层也用 utf8mb4,否则就算数据库层是 utf8mb4,连接层用了 latin1,中文还是会出现乱码或变成问号。
我一般在配置里把服务端字符集写死,避免个例意外。编辑配置文件:
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf # Ubuntu 路径 sudo vim /etc/my.cnf # CentOS 路径建议追加以下内容:
[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci skip-name-resolveskip-name-resolve的意思是禁止 MySQL 反向解析客户端域名,这样连接时只走 IP,能显著加快远程连接速度,也能规避某些环境下反解 DNS 超时导致连不上的问题。加完之后重启 MySQL:
sudo systemctl restart mysql # Ubuntu sudo systemctl restart mysqld # CentOS重启后验证:
mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set_server';"4.3 开启远程访问的正确姿势
默认情况下 MySQL 只监听 127.0.0.1,也就是仅限本机连接。如果你的应用和数据库不在同一台服务器上,就需要改动两个地方:监听地址和用户授权。
先说监听地址。Ubuntu 上配置文件一般在/etc/mysql/mysql.conf.d/mysqld.cnf,CentOS 在/etc/my.cnf,找到这一行:
bind-address = 127.0.0.1改成:
bind-address = 0.0.0.0这意味着 MySQL 监听所有网卡,生产环境建议改成具体的业务网段或内网 IP,不要无脑 0.0.0.0。
然后设置远程用户。不要直接给 root 开远程权限,建一个专用账号:
CREATE USER 'appuser'@'192.168.1.%' IDENTIFIED BY '强密码'; GRANT ALL PRIVILEGES ON mydb.* TO 'appuser'@'192.168.1.%'; FLUSH PRIVILEGES;192.168.1.%的意思是只允许这个网段访问。如果应用服务器 IP 固定,直接写具体 IP 更安全。如果你不确定业务网段,可以先允许特定 IP,等验证通了再放宽,不要一开始就给%。
4.4 时区问题也要顺手处理
很多应用会需要正确的数据库时间。MySQL 默认时区跟随系统,但如果你跨机房部署、或者系统时区本身设置不对,数据库时间就会偏。可以在配置里写死:
[mysqld] default-time-zone = '+08:00'如果要用命名时区,比如Asia/Shanghai,需要先导入系统时区表:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql导入完成后,才可以在配置里写default-time-zone = 'Asia/Shanghai'。这个操作比较容易被忽略,但一旦应用时间对不上,排查起来真的很费劲。
5. 常见问题与排查技巧实录
5.1 端口明明显示监听,但连接超时或拒绝
遇到这种情况,我先按三层来排查:
第一层监听。ss -lntp | grep 3306,如果输出为空,说明 mysqld 没起来或者没监听这个端口,去日志里找原因。
第二层防火墙。Ubuntu 常见的是ufw,CentOS 是firewalld。如果服务正常监听,但远程连接超时,大概率是防火墙拦截。放行命令:
sudo ufw allow 3306/tcp # Ubuntu sudo firewall-cmd --permanent --add-port=3306/tcp # CentOS sudo firewall-cmd --reload # CentOS第三层用户权限。如果 ping 得通但 MySQL 报Host 'xxx' is not allowed to connect to this MySQL server,那就是用户 host 配置的问题,回到user表里看这个用户允许的来源主机是不是覆盖了当前 IP。
5.2 Access denied 和 Authentication plugin 错误
在 MySQL 8.0 里,默认认证插件是caching_sha2_password。新版客户端没问题,但一些老版本客户端、老语言驱动可能只支持mysql_native_password,连接时就会报:
Authentication plugin 'caching_sha2_password' cannot be loaded解决办法是把这个用户改为兼容的认证方式:
ALTER USER 'appuser'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';但注意,mysql_native_password在 MySQL 8.0 里已经被标记为废弃,能不用就不用,最好去升级客户端。如果只是你自己的旧工具临时连一下,可以这么改;生产环境我建议直接换客户端版本。
5.3 启动失败:错误日志怎么看
- Ubuntu 错误日志:
/var/log/mysql/error.log - CentOS 错误日志:
/var/log/mysqld.log
很多时候systemctl status mysql只告诉你failed或active (exited),根本原因要去日志里找。最常见的两种:
第一种是数据目录权限不对。MySQL 会要求数据目录属主是mysql用户,如果你用 root 手动跑过初始化或者把目录拷贝到别的地方,就可能出现权限问题,启动时报错Permission denied。解决办法:
sudo chown -R mysql:mysql /var/lib/mysql第二种是配置文件语法错误或变量名不识别。MySQL 8.0 启用了一些严格模式,配置里写了老版本的变量会直接拒绝启动。可以用下面的命令检查配置:
sudo mysqld --verbose --help 2>/dev/null | grep -E '^validate_password'如果配置里确实有不见识的变量,最简单的方式是注释掉重启试试。
5.4 忘记 root 密码的急救流程
这个情况我真的处理过不少次,尤其是那种很久没碰的测试库。MySQL 8.0 重置密码的思路是跳过权限表启动,然后手动改密码。
停止服务:
sudo systemctl stop mysql # Ubuntu sudo systemctl stop mysqld # CentOS以后台安全模式启动:
sudo mysqld_safe --skip-grant-tables --skip-networking &注意--skip-networking必须加,否则相当于开着免密数据库暴露在内网里,非常危险。这个模式只允许本机 socket 连接。
用 root 登录:
sudo mysql -u root然后刷新权限并设置新密码:
FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';操作完以后,把后台 mysqld_safe 进程杀掉,然后正常启动服务:
sudo pkill mysqld sudo systemctl start mysql5.5 常用排查命令速查表
| 目标 | 命令 | 预期结果 |
|---|---|---|
| 查看服务状态 | systemctl status mysql/mysqld | active (running) |
| 查看端口监听 | ss -lntp | grep 3306 | LISTEN状态 |
| 查看 MySQL 版本 | mysql -V | 显示版本号 |
| 查看数据目录权限 | ls -ld /var/lib/mysql | 属主为 mysql:mysql |
| 查看运行日志 | tail -f /var/log/mysql/error.log | 无致命错误 |
| 测试本地连接 | mysql -u root -p -e "SELECT 1" | 返回 1 |
| 测试指定端口连接 | mysql -h IP -P 3306 -u user -p | 正常进入 |
6. 我自己的一些实际经验和后续建议
MySQL 装好只是第一步,真正影响你后续体验的是配置和运维习惯。我个人建议装完以后顺手做三件事:第一,写一个简单的备份脚本,用mysqldump定期把业务库导出来,哪怕是每天凌晨一次全量备份,关键时刻能救命;第二,把慢查询日志打开,超过 2 秒的 SQL 记录下来,以后排查性能瓶颈可以直接看日志;第三,监控好磁盘和数据目录的增长,我有一次就是没注意磁盘满了,MySQL 直接拒绝写入,业务反馈过来才发现。
另外,尽量别在生产环境用 root 账号跑业务连接。建一个专用账号,权限只给到业务需要的库,这是成本最低的安全防护。如果后面遇到性能问题,先看EXPLAIN,再考虑调innodb_buffer_pool_size,这一步能让你的 MySQL 从“能跑”变成“跑得稳”。
坦率讲,Linux 装 MySQL 这个东西,第一次折腾可能会花掉一下午,大部分时间都耗在权限和认证上。但只要完整地走过一遍,后面的安装基本就是肌肉记忆。希望这篇内容能让你少走一点弯路。