Linux下装MySQL,说难不难,说简单吧,几乎隔三差五就能在群里看到有人贴出一张报错截图,要么是ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock',要么是装完之后root密码怎么试都不对,甚至还有的连装都没装上,直接被yum源里的MariaDB给“截胡”了。这些都是我在自己的服务器和客户现场实打实踩过的坑,所以想写一篇真正能落地、能复现的Linux MySQL安装教程,把选型逻辑、完整操作步骤、初始化配置和高频故障排查链路都梳理清楚,希望能帮你少走几个来回。
这篇文章适合三类人:第一次在Linux上装MySQL的纯新手、从Windows转过来不太适应命令行的同学,以及装过但总在某个环节翻车的“老踩坑人”。内容以CentOS/RHEL系的yum/dnf安装为主,同时会覆盖Ubuntu/Debian系和通用二进制包的差异点,只要按章节走完,大概率能一次跑通。
1. 为什么同一个安装教程,别人装得成你装不成
1.1 三个影响成败的前置认知
网上搜“Linux安装MySQL”,能搜出一堆教程,但很多人拿着教程直接套,结果第一步就挂了。原因很简单:Linux发行版之间的差异比Windows大得多,同一个命令在CentOS 7上能跑,在Ubuntu 22.04上可能压根不存在,反之亦然。
第一个需要建立的认知是包管理器的区别。CentOS/RHEL老版本用yum,CentOS 8及以后用dnf,Ubuntu/Debian用apt。虽然dnf可以兼容yum命令,但仓库配置文件的路径、软件包命名规则都不一样。MySQL官方仓库提供了针对不同系统的rpm包和deb包,选错了就是白费力。
第二个认知是MySQL和MariaDB不是一回事。CentOS 7默认的软件源里有个mysql包,但那个包指向的是MariaDB——MySQL被Oracle收购后,原开发团队分叉出来的社区版本。如果你直接yum install mysql,装出来的东西虽然命令很相似,但数据目录结构、配置文件位置、部分系统表都有差异,网上针对官方MySQL的教程可能对不上号。这也是很多新手“照着教程做却莫名其妙”的根源。
第三个认知是MySQL 8.0和5.7差别很大。现在官方默认推8.0,默认认证插件是caching_sha2_password,密码策略默认是强校验,这些特性在5.7时代都不存在。如果你下载的是8.0,却拿5.7的教程来配置,很容易在密码、远程连接环节卡住。
1.2 该怎么判断“该用哪套命令”
在动手之前,先用几条命令确认系统基本信息,别凭感觉猜:
# 查看发行版信息 cat /etc/os-release # 查看系统架构 uname -m # 查看包管理器 which yum dnf apt-get 2>/dev/null以我自己的经验,CentOS 7.x就用yum,CentOS 8+/Rocky Linux/AlmaLinux用dnf(yum命令也兼容),Ubuntu 20.04/22.04/Debian用apt。架构基本都是x86_64,少数ARM服务器要注意选对二进制包。
提示:如果你的系统里已经自带了MariaDB,建议先确认一下自己到底需要哪个。MariaDB和MySQL在大部分场景下可以互相替代,如果你没有特别强制的兼容性需求,用系统自带的MariaDB其实更省事。如果确实需要官方MySQL,再走下面的卸载清理流程。
1.3 一个很容易被忽略的坑:残留的旧版本
不少人装MySQL失败,不是新装的问题,而是机器上有残留。以前曾经手动装过MySQL、或者系统自带了MariaDB,数据目录、配置文件、服务脚本都会和新装的产生冲突。最常见的现象是:新装完MySQL,systemctl start mysqld却提示端口被占用,或者数据目录初始化失败。
所以在安装之前,必须先确认一下是否存在旧版本:
# 检查是否装了MySQL/MariaDB相关的rpm包 rpm -qa | grep -iE 'mysql|mariadb' # 检查是否已存在数据目录 ls -ld /var/lib/mysql 2>/dev/null ls -ld /etc/my.cnf 2>/dev/null # 检查3306端口是否被占用 ss -lntp | grep 3306这几条命令的输出决定了后续是直接装,还是先清理一波。很多教程不会讲这个准备步骤,但这恰恰是线上服务器安装最常踩的雷。
2. 安装方式的选择:官方仓库、二进制包、源码编译还是容器
2.1 四种方式的优缺点对比
我见过有些人一上来就编译源码,搞得特别复杂。实际上,MySQL的安装方式至少有四种,每种都有自己的适用场景,没必要为了“显得专业”而去编译。
| 安装方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 官方Yum/Apt仓库 | 依赖自动解决、升级方便、默认配置规范 | 需要联网、仓库地址需要额外配置 | 绝大多数联网服务器 |
| 通用二进制包 | 不依赖网络、路径可控、适合离线环境 | 需要手动处理依赖、后续升级麻烦 | 内网环境、特殊定制路径 |
| 源码编译 | 可自定义编译参数、性能可优化 | 编译时间长、依赖多、容易出错 | 特殊硬件平台、深度优化需求 |
| Docker容器 | 部署快、隔离性好、环境一致 | 数据卷管理有门槛、性能略损耗 | 开发测试、微服务场景 |
2.2 为什么我推荐官方仓库
如果你问我的意见,常规环境我优先推荐官方仓库。原因有三点:
第一,依赖自动解决。MySQL不是单个二进制文件,它依赖libaio、ncurses等一堆基础库,用通用二进制包的时候,缺哪个就得手动装哪个,来回折腾。用仓库安装,包管理器会把这些依赖一并处理掉。
第二,后续升级很简单。直接yum update mysql-server或者apt upgrade就能升级小版本,安全补丁可以及时打上。二进制包想升级就得重新下载、重新部署,很麻烦。
第三,配置文件和服务脚本规范。官方仓库装出来的服务脚本、日志路径、目录权限都是约定俗成的,出了问题网上能搜到大量一致的经验。二进制包如果自定义路径,很多默认行为会变得“和别人不一样”。
2.3 什么情况选通用二进制包
通用二进制包(Generic Binary)并非一无是处。如果你所在的内网环境无法访问外网,或者公司要求MySQL必须装在/opt/mysql这种非标准路径,二进制包反而是最佳选择。
它本质上就是把官方编译好的文件解压到指定目录,然后手动初始化数据目录、创建系统用户、编写服务脚本。操作逻辑不复杂,但步骤琐碎。我这里提一下,不做展开,因为大多数读者用不到。
容器方式则适合开发环境快速起一个实例,docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=xxx -p 3306:3306 mysql:8.0一行搞定。但生产环境的性能和数据卷管理,建议还是老老实实用物理机或虚拟机安装。
3. 从零开始:官方仓库一步步安装MySQL 8.0的完整流程
3.1 配置官方Yum仓库
我以CentOS 7为例,先把官方仓库装上去:
# 安装官方MySQL Yum仓库 rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm如果是Rocky/AlmaLinux 9,把el7替换成el9;CentOS 8替换成el8。安装完仓库包后,查看一下仓库列表确认生效:
yum repolist enabled | grep mysql正常情况下会看到mysql80-community这一行。这一步做完,系统就知道去哪里找MySQL 8.0的rpm包了。
3.2 清理旧的MariaDB残留
如果第1步检查发现有MariaDB,建议先卸载:
systemctl stop mariadb # 先停服务 yum remove -y mariadb* rm -rf /var/lib/mysql # 删除旧数据目录这一步要谨慎。/var/lib/mysql里面如果有你之前的重要数据,先备份再删。在真实服务器上,删除数据目录之前一定要三思。我自己曾经因为图省事直接删,结果发现里面是一个测试环境的历史数据,虽然不心疼但也被同事提醒了一顿。数据无价,操作要规范。
3.3 安装MySQL服务端和客户端
yum install -y mysql-community-server mysql-community-client这里mysql-community-server是服务端,mysql-community-client是命令行客户端。有些教程只装server,默认会连带把client装上,但为了明确,我习惯两项都写上。
安装过程会自动创建mysql系统用户和/var/lib/mysql数据目录。装完之后可以用rpm -qa | grep mysql确认版本,一般来说会看到mysql-community-server-8.0.x。
3.4 启动服务并获取初始密码
MySQL 8.0在首次启动时会自动初始化数据目录,并生成一个临时root密码,这个密码只能通过日志文件查看:
systemctl start mysqld systemctl status mysqld # 查看初始密码 grep 'temporary password' /var/log/mysqld.log输出类似这样:
[Note] A temporary password is generated for root@localhost: xxxxxxxx把这个临时密码记下来,下一步要用。如果日志里没找到,可能是/var/log/mysqld.log路径不同,用find / -name mysqld.log找一下。
3.5 Ubuntu/Debian系统的差异
Ubuntu/Debian系统的流程类似,但仓库包换成了deb格式:
# 下载官方apt仓库配置包 wget https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb dpkg -i mysql-apt-config_0.8.29-1_all.deb # 弹窗里选择MySQL 8.0,然后OK apt update apt install -y mysql-serverUbuntu安装过程中会直接让你设置root密码,比CentOS少一个“扒日志找临时密码”的步骤。但Ubuntu的MySQL配置文件是/etc/mysql/mysql.conf.d/mysqld.cnf,和CentOS的/etc/my.cnf不一样,这是一个容易混淆的点。
4. 初始化安全配置与基础设置:别让数据库“裸奔”
4.1 跑一遍安全初始化脚本
拿到临时密码后,第一件事是登录并跑安全初始化脚本:
mysql -uroot -p # 输入上面日志里的临时密码登录成功后,执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的新密码'; FLUSH PRIVILEGES;注意:MySQL 8.0 默认密码策略要求密码至少8位,且包含大小写字母、数字和特殊字符。如果你设置的密码太简单,会直接报
ERROR 1819。这也是很多新手觉得自己“密码明明输对了却设置失败”的原因。
跑安全脚本的方式有两种,一种是交互式执行mysql_secure_installation,按提示一步步来;另一种是手动执行SQL。我个人更推荐手动SQL,因为交互式脚本在自动化部署时不好处理。下面是完整的初始化SQL:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Strong@Passw0rd'; -- 删除匿名用户(默认MySQL已经不存在匿名用户,这步可以跳过) DROP USER IF EXISTS ''@'localhost'; -- 删除测试数据库 DROP DATABASE IF EXISTS test; FLUSH PRIVILEGES;4.2 理解MySQL 8.0的密码验证策略
安装完成后默认的密码策略是validate_password.POLICY = 1(MEDIUM级别)。这个策略直接影响后续创建用户的体验。如果你是在开发环境,希望密码简单一点,可以降低策略:
SET GLOBAL validate_password.policy = LOW; SET GLOBAL validate_password.length = 6;但这只是在运行时生效,重启后会恢复默认。想永久修改,需要在/etc/my.cnf的[mysqld]段加上:
[mysqld] validate_password.policy = LOW validate_password.length = 6顺便说一下,MySQL 8.0里validate_password是插件,不是单独的服务。如果SET GLOBAL时报变量不存在,多半是插件没有加载,需要检查INSTALL COMPONENT 'file://component_validate_password';是否执行过。
4.3 创建专属账号:不要总用root
我见过太多人所有应用都用root连数据库,这是一个很不好的习惯。root在MySQL里拥有全部权限,一旦业务连接串泄露,等于把整个数据库拱手让人。正确的做法是为每个应用创建独立的账号,只授权需要的库:
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'App@Passw0rd'; GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'localhost'; FLUSH PRIVILEGES;这里的mydb.*表示mydb库下的所有表。如果应用需要从远程连接,把localhost换成%或者具体IP网段。注意,'app_user'@'%'和'app_user'@'localhost'是两个不同的账号,可以共存。
4.4 统一字符集:避免中文乱码
MySQL 8.0默认字符集已经是utf8mb4,但老版本迁移过来的库可能是latin1或utf8mb3。为了避免中文乱码,建议在/etc/my.cnf中显式设置:
[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci [client] default-character-set = utf8mb4然后重启MySQL:
systemctl restart mysqld登录后查看:
SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';如果所有character_set_*开头的变量都是utf8mb4,就说明配置生效了。这里有个小技巧:character_set_database和character_set_server这两个变量最容易漏,因为它们是由建库时的默认值决定的。新建库之前确认好,否则后续改起来很麻烦。
4.5 设置开机自启
这一步最简单但也最容易被忽略:
systemctl enable mysqld如果你用docker run跑的MySQL,要设置restart: always策略,否则机器重启后容器不会自动拉起。
5. 安装后必踩的几个坑:error 2002与连接异常
5.1 error 2002的完整排查链路
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock'这个报错,几乎每个MySQL新手都会遇到。它的字面意思是:客户端尝试通过socket文件连接MySQL服务,但连接失败。注意,这里的关键词是socket文件,不是TCP端口。
出现这个错误,按下面的链路排查:
第一步,确认服务是否在运行:
systemctl status mysqld如果服务没启动,先systemctl start mysqld再看。
第二步,如果服务在运行,确认socket文件的实际位置:
find / -name "*.sock" -o -name "mysql.sock" 2>/dev/null通常socket文件应该在/var/run/mysqld/mysqld.sock或者/tmp/mysql.sock,具体位置由配置文件决定。可以查看:
grep -r "socket" /etc/my.cnf /etc/mysql/ 2>/dev/null第三步,如果socket文件路径和报错里的路径不一致,说明默认找错了。可以直接指定socket路径连接:
mysql -uroot -p --socket=/var/run/mysqld/mysqld.sock或者改用TCP方式连接:
mysql -uroot -p -h 127.0.0.1 -P 3306我遇到的实际情况是:大多数error 2002都是因为服务根本没启动,或者服务启动后socket文件被清理了。前者用systemctl start解决,后者一般是权限或SELinux问题,需要往下查。
5.2 MySQL 8.0认证插件导致的连接失败
装好MySQL 8.0后,如果本地连接正常,但从另一台机器用客户端连不上,报错往往是Authentication plugin 'caching_sha2_password' cannot be loaded或者Access denied。
原因:MySQL 8.0默认的认证插件是caching_sha2_password,而很多老版本客户端(比如5.7时代编译的PHP扩展、老版Navicat)不支持这个插件。
解决办法有两种:
第一种,创建用户时指定老认证插件:
CREATE USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';第二种,修改已有用户的认证方式:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';或者在/etc/my.cnf里全局指定默认认证插件:
[mysqld] default_authentication_plugin = mysql_native_password不过我个人不建议一上来就全局改默认插件,因为这等于放弃8.0的更强认证方式。更好的做法是:升级客户端,新版本客户端都支持caching_sha2_password。只有实在无法升级客户端时才用mysql_native_password兼容。
5.3 防火墙和SELinux:连不上的“隐形元凶”
如果你从远程连接时发现端口超时、或者一开始能连后来突然连不上,多半是防火墙或SELinux的问题。
CentOS 7/RHEL 7默认防火墙是firewalld,检查3306端口是否放行:
firewall-cmd --list-ports # 添加端口 firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload如果你用的云服务器,还要在云控制台的安全组里放行3306端口。这一步即使本地防火墙开了,安全组不放行也是白搭。
SELinux的问题更隐蔽。查看SELinux状态:
getenforce如果是Enforcing,MySQL可能会被限制。解决方式:
# 允许MySQL网络连接 setsebool -P mysql_connect_any 1 # 或者为3306端口添加SELinux端口映射 semanage port -a -t mysqld_port_t -p tcp 3306如果semanage命令不存在,需要先安装policycoreutils-python-utils或者policycoreutils-python包。
5.4 数据目录权限错误
还有一类比较常见的启动失败场景:systemctl start mysqld直接报[ERROR] Could not open required defaults file或者Permission denied。这通常是数据目录或配置文件的属主不对。
chown -R mysql:mysql /var/lib/mysql chown -R mysql:mysql /var/run/mysqld chmod -R 750 /var/lib/mysql然后重启服务。这一点在恢复备份、迁移数据目录时特别容易踩,因为拷贝文件会改变属主和权限。
6. 装好之后的日常管理与常用操作
6.1 服务管理的基本命令
安装完成、测试能连上后,先把这几个命令记牢。我每天在服务器上用得最多的就这几个:
systemctl start mysqld # 启动 systemctl stop mysqld # 停止 systemctl restart mysqld # 重启 systemctl status mysqld # 查看状态 systemctl enable mysqld # 设置开机自启日志文件默认在/var/log/mysqld.log,排查问题时第一件事看这个文件的尾部:
tail -100 /var/log/mysqld.log6.2 日常高频SQL操作速查
安装完之后,紧接着面临的就是日常使用。以下是几个我帮别人排查问题时经常用到的SQL,也是很多新手刚学MySQL时容易搞混的:
修改一条记录:
UPDATE users SET status = 1 WHERE id = 10;注意,MySQL 8.0如果以safe-update模式启动,不带WHERE条件的UPDATE会直接报错。这是个保护机制,能防止误操作。日常操作中,执行UPDATE前最好先用SELECT确认条件:
SELECT * FROM users WHERE id = 10; UPDATE users SET status = 1 WHERE id = 10;排序查询:
SELECT * FROM products ORDER BY price DESC LIMIT 10;ORDER BY默认是升序ASC,降序要显式写DESC。
设置字段默认值:
ALTER TABLE orders ALTER COLUMN status SET DEFAULT 0;ALTER COLUMN ... SET DEFAULT用于修改默认值,很多人容易把它和ALTER TABLE ... MODIFY COLUMN搞混。前者只改默认值,后者会重定义整列类型和约束。
6.3 保留一个基础备份习惯
装好MySQL之后,我最想强调的一件事不是配置调优,而是备份。我见过太多人在装完之后立刻开始建库建表,却从没想过如果数据没了怎么办。
最简单的逻辑备份工具是mysqldump,一条命令就能备份整个库:
mysqldump -uroot -p --single-transaction --routines --triggers --events mydb > mydb_backup_$(date +%F).sql恢复的时候:
mysql -uroot -p mydb < mydb_backup_$(date +%F).sql--single-transaction参数是InnoDB引擎下保证备份一致性又不锁表的关键,生产环境务必加上。--routines、--triggers、--events分别备份存储过程、触发器、事件,很容易被忘掉。
个人建议:安装配置完成后,先把这个备份命令放到crontab里,就不用担心数据丢了:
0 2 * * * /usr/bin/mysqldump -uroot -p'密码' --single-transaction --routines --triggers --events mydb > /backup/mydb_$(date +\%F).sql7. 最后再补充几个实操细节
这篇关于Linux MySQL安装的教程,主要流程到这里基本结束了,但我还有几个实操细节想单独提一下,这些都是我真实经历后觉得值得记下来的点。
第一个细节:装完后别急着调参。我看过很多人装完MySQL第一件事就是改innodb_buffer_pool_size、max_connections,觉得自己调优很专业。但实际上,初期除非明确知道业务压力,否则默认配置已经经过了官方优化。我以前在一台8G内存的服务器上把innodb_buffer_pool_size调到6G,结果系统直接卡死,因为忘了还有操作系统和其他服务在跑。合理做法是先用默认配置跑一段时间,看SHOW ENGINE INNODB STATUS和SHOW GLOBAL STATUS再决定怎么调。
第二个细节:用mysql_config_editor保存登录凭据,别把密码写在命令行里。如果你要把自动备份写进crontab,密码写在命令行里会导致两个问题:一是ps命令能看到密码,有泄露风险;二是密码里有特殊字符时,shell转义特别容易出错。更安全的做法是:
mysql_config_editor set --login-path=backup --host=localhost --user=root --password然后备份命令变成:
mysqldump --login-path=backup --single-transaction --routines --triggers --events mydb > mydb_backup.sql密码不再出现在命令行里,日志和进程列表都干净了。
第三个细节:MySQL 8.0的caching_sha2_password首次连接会走TLS或者RSA密钥交换,如果你是在纯内网环境、且客户端版本较老,第一次连接可能会卡住或报错Public Key Retrieval is not allowed。解决方法有两个:连接串里加allowPublicKeyRetrieval=true,或者用户指定用mysql_native_password。我处理过一个客户环境,就是卡在这里,折腾半天才发现是JDBC连接串参数问题。
第四个细节:my.cnf配置文件的层级。Linux下MySQL会依次读取/etc/my.cnf、/etc/mysql/my.cnf、~/.my.cnf等文件,后面读取的配置会覆盖前面的。如果发现某个参数改了没生效,先查一下是不是被后面的配置文件覆盖了。我遇到过一次,改了/etc/my.cnf但没生效,排查半天发现是/etc/mysql/conf.d/下有个残留的配置文件把它压过去了。
踩过几次坑之后我现在装MySQL已经形成了一套固定动作:先确认系统版本和包管理器,再检查残留,接着装官方仓库、安装、启动、查临时密码、改密码、安全初始化、建业务账号、配字符集、开自启、做一次备份,最后才交给业务部署。这套流程走下来,基本没有再翻过车。你按这个思路走,大概率也能一次顺利跑通。