最近在一台CentOS 7.9服务器上重新部署MySQL 5.7.44,过程中踩了不少坑,趁着记忆还热乎,把完整的安装、配置、排错流程整理出来。不管你是刚接触Linux的新手,还是已经能熟练使用常用命令的老手,在CentOS上安装MySQL这件事看似简单,但一个不小心就会遇到依赖冲突、权限错乱、启动失败这些麻烦。这篇文章我会用最直接的方式,分别讲清用Yum源和RPM包安装的完整流程,还会补充大量实测出来的排错经验。
1. 安装前的环境准备与方案选型
1.1 确认系统版本、硬件与网络环境
很多新手拿到一台服务器就急着装MySQL,结果装一半才发现系统是CentOS 8,或者架构对不上,白折腾半天。建议第一步先把环境信息摸清楚,执行下面几条命令:
cat /etc/centos-release uname -m nproc free -h df -hcat /etc/centos-release看系统版本,比如CentOS Linux release 7.9.2009 (Core),或者8.x系列。uname -m看CPU架构,最常见的是x86_64,如果是aarch64(ARM架构)服务器,仓库包的选择会不一样。nproc看CPU核心数,free -h看内存,df -h看磁盘空间。MySQL 5.7最低要求内存不低于1GB,空闲磁盘不少于5GB,但实际生产环境2GB内存加20GB可用磁盘是起点,否则跑一会儿就会因为内存耗尽或日志撑爆磁盘出各种奇怪问题。
另外网络环境决定你能不能顺利下载依赖包。如果是内网服务器,没法直接访问外网,就需要提前下载好RPM包和依赖,或者配置内网镜像源。这里多说一句,很多人喜欢把系统自带的最小化安装再精简一遍,但MySQL需要一些基础依赖库,例如libaio、numactl等,后面会讲到。
1.2 三种主流安装方式,到底选哪种
CentOS上装MySQL,主流路线有三条:官方Yum源、RPM包手动安装、源码编译。还有一部分人直接拉Docker镜像,这里也顺便说一下。
- 官方Yum源安装:最省心,适合大部分场景。通过MySQL官方提供的
repo包,把Yum源指向官方仓库,然后yum install mysql-community-server一条命令自动解决所有依赖,后续升级也方便。 - RPM包手动安装:适合内网环境、离线安装,或者需要精确控制版本的场景。从官方站点下载对应的
rpm-bundle.tar,解压后用rpm -ivh按顺序安装,依赖需要自己处理。 - 源码编译:适合需要深度定制编译参数、关闭某些插件或者优化特定硬件的场景。编译耗时耗力,配置不当还可能性能反而不如二进制包,非特殊需求一般不建议。
- Docker安装:用镜像跑MySQL是现在很多开发和测试环境的标准做法,但生产环境需要自行处理数据卷、网络、日志、自动重启等问题。如果只是本地练手,Docker很舒服,真正上生产我还是建议直接用物理或虚拟机的系统服务方式,少一层中间层,排错也简单。
我用得最多的还是官方Yum源。原因很简单:官方仓库的版本经过专业测试,依赖处理自动化,不会出现手动装漏一个.so库然后服务启动失败的问题。而且官方Yum源支持同时安装5.7和8.0系列,切换版本也方便。
2. 使用官方Yum源安装MySQL 5.7与8.0
2.1 先清理系统自带的MariaDB和残留MySQL
CentOS 7默认自带MariaDB,它是MySQL的一个分支,很多命令和客户端兼容,但因为服务和数据文件与MySQL不兼容,直接装MySQL会冲突。先看系统里有没有:
rpm -qa | grep -E 'mariadb|mysql'如果看到mariadb-libs这类包,就用yum remove mariadb*把它卸掉。注意有些系统库可能依赖于它,比如postfix,如果报依赖错误,可以加上--nodeps强行删除,但删除后记得后续排查其他服务是否正常。这一步不做干净,后面MySQL启动时可能会出现socket文件冲突或者库文件混乱的问题。
另外,如果之前已经装过MySQL但没装完整,重新安装前最好先清理旧数据和旧配置,防止残留的/etc/my.cnf干扰新服务。默认数据目录在/var/lib/mysql,如果里面已经有库,且不是你想保留的,直接把整个目录移走或删除都可以。
systemctl stop mysqld 2>/dev/null rm -rf /var/lib/mysql /etc/my.cnf /etc/my.cnf.d2.2 添加官方Yum仓库并验证可用性
MySQL官方提供了一个集成仓库的RPM包,安装这个包之后,Yum就能自动识别MySQL的软件源。5.7对应的是mysql57-community-release,8.0对应的是mysql80-community-release。以CentOS 7为例,执行:
yum install -y https://repo.mysql.com/mysql57-community-release-el7-11.noarch.rpm如果想装8.0,就把包名换成mysql80-community-release-el7-7.noarch.rpm。安装完成后,检查仓库是否生效:
yum repolist enabled | grep mysql你会看到mysql57-community、mysql-tools-community之类出现了。这时还可以先查一下当前仓库里MySQL的可用版本:
yum list available --showduplicates mysql-community-server如果系统年久失修,连GPG密钥都可能过期。遇到GPG key retrieval failed的报错,可以手动导入官方密钥,或者更新mysql-public-key.asc。不过正常情况下,安装了release包后密钥会一起放入,基本不用管。
2.3 安装MySQL服务器并启动初始化
现在直接安装服务器程序:
yum install -y mysql-community-server安装过程会列出依赖,比如mysql-community-libs、mysql-community-common,全自动搞定,非常省事。安装完成后,先初始化数据目录再启动服务。5.7和8.0的初始化不太一样:5.7的默认配置文件/etc/my.cnf里已经配置了log-error,安装后首次启动时,MySQL会自己完成初始化,并生成临时root密码。因此直接启动就可以:
systemctl start mysqld systemctl enable mysqld systemctl status mysqld启动成功的标志是状态显示active (running)。如果失败,请先看第5章的排错内容。启动以后,MySQL已经在/var/lib/mysql下写好了系统库和默认数据文件,挺快的。
2.4 拿到临时密码并完成root改密
5.7和8.0都开启了密码用过期机制,首次启动会生成一个随机临时密码,记录在错误日志里。找到它的命令是:
grep 'temporary password' /var/log/mysqld.log然后登录:
mysql -uroot -p输入刚才的临时密码,进入后立刻修改root密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';注意MySQL默认启用了密码校验插件,要求密码至少包含大写字母、小写字母、数字和特殊符号,长度不少于8位。如果你觉得这太苛刻,可以降低策略,后面会在第3章详细写。改完密码之后,建议执行FLUSH PRIVILEGES,其实ALTER USER之后不需要这一步,但做一次无妨。
3. 修改核心配置与安全加固
3.1 调整my.cnf,让MySQL更贴业务
/etc/my.cnf是MySQL的主配置文件,5.7和8.0默认安装后会带上一个基础配置,其实内容很少,很多默认值对生产环境并不适合。就拿我最近这台业务服务器来说,默认配置跑起来后,没几天就发现连接数不够,日志混乱,字符集也是老旧设定。分享一段常用配置,可以直接存进/etc/my.cnf:
[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid character-set-server=utf8mb4 collation-server=utf8mb4_general_ci port=3306 bind-address=0.0.0.0 max_connections=500 max_connect_errors=1000 wait_timeout=600 interactive_timeout=600 key_buffer_size=64M innodb_buffer_pool_size=1G innodb_log_file_size=256M innodb_flush_log_at_trx_commit=1 innodb_file_per_table=1 slow_query_log=1 slow_query_log_file=/var/log/mysql-slow.log long_query_time=2这里重点解释几个关键参数的意图:
character-set-server=utf8mb4决定默认字符集,utf8mb4能完整存储中文和emoji,而utf8是历史遗留问题,很多地方是不完整的。bind-address=0.0.0.0让MySQL允许从任意IP访问,注意这时候必须通过防火墙限制来源,不然等于裸奔。max_connections根据业务评估,连接数过多会内存翻倍增长,过少则应用经常报Too many connections。innodb_buffer_pool_size决定InnoDB缓存池大小,这个直接决定读写性能,通常设为物理内存的60%~70%比较合理。1G内存的机器就不要设1G,否则系统内存被吃光。我建议内存2G的机器设512M,4G的设1.5G,照此推。slow_query_log开启慢查询日志,线上排查性能问题必备。
配置改完后,重启服务:
systemctl restart mysqld建议每次改配置后用mysqld --validate-config先验证配置是否有语法错误,6.0.8以上的版本这命令还支持检查参数有效性。如果没有这个命令,就多留意报错日志。
3.2 创建业务账号,配置远程访问
root账号极其敏感,生产环境绝对不能拿root给应用连接。正确做法是创建一个专用账号,只授权应用需要的数据库。
CREATE USER 'appuser'@'%' IDENTIFIED BY 'StrongPass@2024'; GRANT SELECT, INSERT, UPDATE, DELETE ON myapp_db.* TO 'appuser'@'%'; FLUSH PRIVILEGES;'appuser'@'%'代表来自任意主机的appuser账号,为了安全可以缩小范围,比如应用服务器IP是192.168.1.100,就写'appuser'@'192.168.1.100'。这样即使密码泄露,攻击面也小很多。
创建完账号,还要检查系统防火墙是否放行3306端口:
firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload如果你用的是云厂商的安全组,还要在管理后台额外放行。很多新手本地防火墙关了,结果被云安全组拦在外面,一脸懵。
3.3 密码策略放宽与安全清理
MySQL的validate_password插件会强制复杂密码,开发环境或者老系统里,这简直让人抓狂。可以动态修改校验级别:
SET GLOBAL validate_password_policy = LOW; SET GLOBAL validate_password_length = 6;但注意,重新启动MySQL实例后这两项配置会重置。想要永久生效,把下面两行加进my.cnf:
validate_password.policy=LOW validate_password.length=68.0的变量名带validate_password.*前缀,5.7是validate_password_policy,注意区分。
安全清理方面,全新的MySQL实例默认会带着test库,直接删掉。还有匿名用户,也可以顺手清理:
DELETE FROM mysql.user WHERE User=''; DROP DATABASE IF EXISTS test; FLUSH PRIVILEGES;另外,远程登录尽量别用root。即使要用,也建议限定来源IP。
4. 数据目录、日志与备份策略
4.1 把数据目录迁移到底层数据盘
很多服务器会有系统盘和数据盘之分。默认情况下MySQL数据存在/var/lib/mysql,系统盘如果满了,数据库就挂了。把数据目录迁移到挂在/data的独立数据盘,是很常见的需求。
操作流程分几步:
# 1. 停止服务 systemctl stop mysqld # 2. 复制数据目录到新位置 cp -a /var/lib/mysql /data/mysql # 3. 修改配置 vim /etc/my.cnf # 把 datadir=/var/lib/mysql 改为 datadir=/data/mysql # 4. 修改SELinux上下文,否则启动失败 semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?" restorecon -Rv /data/mysql # 5. 启动服务 systemctl start mysqld如果你的系统启用了SELinux(CentOS 7默认),忘记第三步,MySQL启动时会疯狂写Permission denied到日志。当然也可以直接关闭SELinux,但我不建议,宁可正确配置上下文。
另外,迁移后原本的/var/lib/mysql如果不再使用,可以备份后删除,或者做成软链接,但软链接方案容易搞混权限,建议直接修改datadir。
4.2 binlog、慢查询、错误日志的合理配置
MySQL的日志体系多样,其中binlog(二进制日志)负责记录所有数据变更,是数据恢复和主从复制的基础。默认情况5.7下log-bin是关闭的,生产环境强烈建议开启。在my.cnf中加上:
server-id=1 log-bin=mysql-bin expire_logs_days=7 max_binlog_size=100Mserver-id在主从复制时是必须的,数字任意但集群中必须唯一。expire_logs_days控制清理多少天前的binlog,防止磁盘被撑爆,8.0里有更灵活的binlog_expire_logs_seconds。
错误日志前面已经提到,路径在log-error=/var/log/mysqld.log,如果MySQL起不来,第一件事就是看这个文件。慢查询日志帮助我们找出执行时间超过阈值的SQL,定位性能瓶颈。把它们都配在my.cnf里,线上问题排查会少很多麻烦。数据恢复试验我强烈建议做一次:开好binlog后,建立一个测试库,插入几行数据,然后删库,再通过binlog按时间点恢复。这一套流程熟悉了,遇到真正故障时不慌。
5. 常见问题与排查技巧
5.1 启动失败与日志定位
装完MySQL最常遇到的就是systemctl start mysqld执行后提示失败,但原因却五花八门。先把日志打开,看你现在的错误日志路径是不是/var/log/mysqld.log:
tail -100 /var/log/mysqld.log如果日志里出现Can't create/write to file '/var/lib/mysql/mysql.pid'这类内容,八成是目录权限不对。可以执行chown -R mysql:mysql /var/lib/mysql修正。如果日志显示Unit mysqld.service entered failed state,大概率是配置里写了无效参数。可以尝试用mysqld --user=mysql --verbose --help | grep -A 1 -E 'some-param'确认参数是否被识别。
另外,/var/run/mysqld目录如果不存在,MySQL会启动失败,因为它要放socket和pid文件。解决方法:
mkdir -p /var/run/mysqld chown mysql:mysql /var/run/mysqld5.2 忘记root密码怎么办
忘了root密码是家常便饭,处理思路是跳过权限表,然后把密码改掉。操作步骤:
systemctl stop mysqld mysqld_safe --skip-grant-tables & mysql -uroot进入MySQL后:
FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY 'New_Strong_Pass';注意:在--skip-grant-tables模式下,很多客户端会报Root password is expired,这时先执行FLUSH PRIVILEGES;再改密,就能绕过去。改完密码重启服务即可。如果你用的是MySQL 5.7之前的旧版本,改密码的语法是UPDATE mysql.user SET authentication_string=PASSWORD('...') WHERE User='root'; FLUSH PRIVILEGES;,5.7之后更推荐用ALTER USER。
5.3 远程连接失败:防火墙、SELinux与网络三重排查
客户端连不上MySQL,但本地能登录,这是高频问题。按顺序查:
MySQL用户权限:
'root'@'localhost'和'root'@'%'不是同一个用户,远程连接必须用'用户'@'可访问IP'。先确认你创建的账号是否授权了对应主机。网络端口:在客户端机器上执行
telnet 服务器IP 3306,如果超时,说明中间链路不通。再在服务器上用ss -lntp确认MySQL是否监听在0.0.0.0:3306。如果只监听127.0.0.1,需要把bind-address改成0.0.0.0。防火墙:
firewall-cmd --list-all检查3306是否放行。SELinux:如果你没有配置SELinux上下文,MySQL的网络访问也会被阻断。可以临时执行
setenforce 0测试,如果问题解决了,就找到原因了,再用semanage为MySQL配置上下文。
5.4 MySQL 8.0与5.7差异导致的坑
如果你之前一直用5.7,切到8.0会发现几个非常明显的差异。首先,8.0默认使用caching_sha2_password认证插件,很多老版本的客户端工具,例如PHP 7.1之前的mysqlnd驱动、某些版本的Python驱动,不支持这种认证方式,连接数据库报Authentication plugin 'caching_sha2_password' cannot be loaded。解决办法是把这个用户改成动态密码方式:
ALTER USER 'appuser'@'%' IDENTIFIED WITH mysql_native_password BY 'yourpassword';其次是字符集系列变量,8.0默认已经是utf8mb4,不需要额外设置。还有my.cnf中一些旧参数被移除了,比如query_cache_size,在8.0里已经失效,继续写会启动失败。8.0的官方文档更推荐用performance_schema替代。所以从5.7升级到8.0,不能直接把老配置拷过来用,必须逐个参数照一遍兼容性。
6. 升级路径与彻底卸载
6.1 5.7升级8.0需要注意的事
如果你打算从5.7平滑升到8.0,最稳妥的思路是备份后在新库上恢复,而不是直接原地升级。原因在于8.0对数据字典、事务系统做了大量重构,原地升级需要遵循官方升级路径,稍有不慎就会锁表或损坏数据。我的建议流程:
- 停止写入,全量备份所有库:
mysqldump -uroot -p --all-databases --single-transaction > backup.sql - 在新环境安装MySQL 8.0,用
mysql < backup.sql导入备份。 - 手动验证应用与驱动的兼容性。
有些服务可以接受短时间连接抖动,也可以用mysqlsh utility.upgrade进行原地检查,但必须有完整备份兜底。生产环境不要脑子一热就直接原地升。
6.2 如何彻底卸载MySQL
有时装坏了想重来,或者要切换版本,彻底卸载干净是很关键的。命令如下:
systemctl stop mysqld yum remove -y mysql-community-server mysql-community-libs mysql-community-common mysql-community-client rm -rf /var/lib/mysql /etc/my.cnf /etc/my.cnf.d /var/log/mysqld.log还要检查下有没有残留依赖,比如mysql-community-release这个repo包,如果不想要也一起删掉:
yum remove -y mysql57-community-release删完后用rpm -qa | grep mysql确认无残留。如果只装了server想保留client,那就不要一次性卸掉全部。
这里分享一个自己踩过的坑:有一次卸载没有删掉/var/lib/mysql,重新安装后新数据一直初始化失败,错误提示是数据目录已存在且非空。因为之前库里的表不兼容。后来老老实实把数据目录备份移走,再重装,问题立刻解决。
7. 最后的几个实践心得
装了这么多次MySQL,我个人最推荐的方式还是官方Yum源+systemd管理,省心且可控。遇到问题不要慌,每一步错误信息都能在日志里找到具体原因,关键是知道去哪看日志、看哪些关键词。新同学如果第一遍装完能远程登录,再顺手练一遍数据迁移、binlog恢复,基本就能应对日常运维了。
最后再分享一个小技巧:MySQL的/var/log/mysqld.log会记录启动过程中的所有错误和警告,但日志会滚动覆盖。如果你排查问题需要更早的日志,可以修改my.cnf增加log-error的保留策略,或者结合logrotate定期归档。这个习惯养成后,不管是自己排错还是将来交给同事,都会轻松很多。祝一次安装成功。