很多同学学完了 Linux 基础命令,接着就想搭一套真实的服务来练手。数据库几乎是绕不开的第一站——你想要的数据,后端总要落盘;而落盘这套活儿,绝大多数情况下是交给数据库来干的。在众多数据库中,MySQL 是市场占有率和出镜率都最高的一员,也是你后面学 SQL、做项目、跟后端联调时天天要打交道的对象。
但"数据库"听起来是个挺重的东西,很多同学第一次听到"要在 Linux 上装 MySQL"就发怵。其实你不用怕——Linux 下装 MySQL 有一条非常成熟的政府军路线,就是今天我们这篇要讲的:yum 源 + systemctl 管理服务。整条链路打下来,你会对"软件怎么装、服务怎么起、密码怎么改、数据库怎么连"有完整的体感,后面再遇到别的服务安装,基本都是一通百通。
在动手之前,先把几个高频术语打响,后面会反复用到:
- MySQL:一个开源的关系型数据库管理系统(简称 DBMS / 关系型数据库)。所谓"关系型",简单说就是数据按"表"来组织,表里是一行行的记录,表和表之间可以通过某些字段建立关系。它负责把你程序里存的数据(比如用户信息、订单)持久化到磁盘上,并允许你通过 SQL(Structured Query Language,结构化查询语言)对它进行增删改查。
- 数据目录(datadir):MySQL 真正把数据库文件写进磁盘的那个目录,默认是
/var/lib/mysql。理解它很重要——你以后备份数据、迁移数据、甚至卸载后重新安装想保留旧数据,盯的都是这个目录。 - yum 源:yum 是 CentOS/RHEL 系列自带的包管理工具,用法是
yum install 软件名。它之所以能"一条命令装好软件",是因为它背后连着一大堆"软件仓库",每个仓库是一个.repo配置文件(放在/etc/yum.repos.d/里),里面写着"去哪下载、下载什么版本的软件"。这些仓库就统称 yum 源。 - systemctl:CentOS 7 使用 systemd 系统来初始化和管理后台服务。
systemctl就是跟 systemd 打交道的命令行工具,systemctl start xxx启动服务、systemctl stop xxx停止服务、systemctl enable xxx设置开机自启。 - 初始化:这里指 MySQL 第一次被启动时,系统自动创建它的数据目录结构、生成系统库表、并给 root 用户生成一个临时登录密码的过程。理解这一点,你就能明白"为什么第一次登录要用临时密码"。
- root 用户:数据库里的超级管理员账号。它权限最高,能创建库、创建用户、授权、删库,几乎什么都能干。安装阶段我们直接用 root 练习即可,等学了权限管理再考虑给业务单独建普通用户。
- 权限(privileges):数据库对"某个用户能干哪些事"的一套限制。比如谁能登录、能看哪个库、能不能写数据,都由权限控制着。今天我们会给 root 授权"允许从别的机器远程登录",正是权限操作的一个活例子。
好,术语铺完,开始动手。整篇文章你会顺着一条非常自然的安装主线走下来,我们边装边把每个步骤的道理讲透,最后再用几道思考题帮你巩固。
你应该有的环境准备
在开始之前,请确认你手里有一台能用的 CentOS 7 服务器或虚拟机,并且:
- 你能登录到 root 账号。整条安装/卸载流程,标准动作都是切到 root 下做的:要么直接
su -切到 root,要么每条命令前面加sudo。普通用户有时候确实能跑工具,但像改配置文件、管理服务、操作/var/lib/mysql这种系统级的事,离开 root 八成会碰到"权限不够"的报错。 - 初期练习阶段,先别折腾复杂的多用户。网上的教程会教你做各种用户、授权、安全加固,但那是后话。我们初期就老老实实用 root 一个账号先把 MySQL 的语句玩熟,等后面专门学了用户管理,再回头给业务建专用用户。
- 有个小纪律先记住:凡是装了 MariaDB 或残留的旧 MySQL 的环境,安装前都要先清(卸载)干净,否则两个数据库服务会争抢 3306 端口、抢占数据目录,很容易把自己绊倒。这就是文章第一件事为什么要做"卸载"。
一、检查并卸载自带 / 残留的数据库
CentOS 7 默认自带了一个和 MySQL 几乎同源的数据库 —— MariaDB。它是 MySQL 早期分叉出去的社区分支,安装命令、语法都高度相似,但服务名字、数据文件格式有差别,两者不能混着一起跑。另外,很多服务器上可能之前被折腾过、残留着旧版 MySQL 的安装包。所以我们要做的第一件事,就是先摸清环境里到底有什么,然后清掉。
先检查系统里是否跑着 MariaDB 进程:
ps ajx | grep mariadb
# ps: 查看进程的命令
# ajx 三个选项组合起来, 以能看清进程归属和父子关系的方式列出所有进程
# | 是管道, 把左边的输出作为右边命令的输入
# grep mariadb: 在进程列表里过滤出包含 mariadb 的那几行
# 如果只输出了一条 grep 自己(带 grep --color=auto 字样), 说明没有 mariadb 在跑如果你的环境里确实有 MariaDB 在运行,会出现一行包含 /usr/libexec/mysqld 或 mariadb 关键字的进程记录,那就要先把它停下来:
systemctl stop mariadb.service
# systemctl: 管理系统服务的命令
# stop: 让指定服务停止运行
# mariadb.service: 服务的完整名字, 即 MariaDB 的服务单元用 systemctl stop 时,如果当前不是 root,系统通常会自动弹出一个图形化的鉴权确认(Authenticating as: root 再要你输密码),这正是 CentOS 7 的 polkit 机制在替你完成提权,你输对 root 密码即可。
停掉进程之后,再看系统里有没有残留的安装包:
rpm -qa | grep mariadb
# rpm: Red Hat 系(含 CentOS)的包管理命令
# -qa: query all, 列出所有已安装的软件包名字
# | grep mariadb: 在已装包列表里过滤出带 mariadb 的
# 如果什么也没输出, 说明没有 mariadb 的安装包残留同理可以查一下旧版 MySQL 的安装包:
rpm -qa | grep mysql
# 过滤出所有名字里带 mysql 的已安装包
# 一个典型的输出样例是:
# mysql-community-common-5.7.41-1.el7.x86_64
# mysql-community-server-5.7.41-1.el7.x86_64
# mysql-community-client-5.7.41-1.el7.x86_64
# mysql57-community-release-el7-11.noarch
# 注意: install(安装)版的 mysql-community-* 是我们装了之后才应该出现的;
# 现在这一行的目的, 是看安装【之前】环境里有没有残留, 有就记下来准备卸载如果查出来有 MariaDB,就用 yum 把它整个卸掉:
sudo yum remove mariadb
# sudo: 以 root(超级用户) 权限执行后面的命令
# yum remove: 卸载指定软件包, 这里卸载 mariadb
# 提示: remove 只删软件本身, /etc/my.cnf 配置文件和 /var/lib/mysql 数据目录一般会被保留这里有个重要的备份意识要提前种下:如果这套环境里已经有了你不想丢的旧数据(比如之前别人已经用过了),卸载前先把 /etc/my.cnf 配置文件、/var/lib/mysql 数据目录备份一份。命令大概是:
sudo cp /etc/my.cnf /etc/my.cnf.bak # 备份配置文件, 名字加个 .bak 后缀
sudo mv /var/lib/mysql /var/lib/mysql.bak # 把旧数据目录改名挪走, 而不是删掉(如果你的环境本来就是全新干净的,这两步备份可以跳过。但在"可能丢数据"的操作面前,先备份永远是加分项。)
小思考:卸载 MariaDB 的时候,网上很多教程会让你连
/var/lib/mysql一起删掉,为什么我们在学习中宁可保留也不急着删?详解:
/var/lib/mysql是数据库存放实际数据的目录,也就是我们说的"数据目录"。删掉它等于删掉库里所有数据(如果里面有旧库、旧表,就全没了)。在学习、练习阶段,这个目录里通常没有必须保留的业务数据,删不删都不影响你学会安装;但在生产、有真实数据的环境里,误删数据目录是灾难级的操作。所以更稳妥的习惯是:先改名备份(mv成.bak),而不是直接rm删掉。这样万一后面发现"咦我原来那个库还要用",还能找个地方找回来。养成"动数据前先备份"的肌肉记忆,比记住一串命令重要得多。
二、获取并安装 MySQL 官方 yum 源
环境清干净了,接下来要回答一个关键问题:yum 命令怎么知道去哪下载 MySQL? 如果你直接 yum install mysql,装到的其实是 CentOS 基础仓库里的那个 MySQL(而且版本很旧,甚至可能只是兼容层)。要装到实实在在的官方 MySQL,我们就得先给 yum 安装一个"官方仓库配置文件",也就是MySQL 官方 yum 源。
MySQL 官方的 yum 源托管在 http://repo.mysql.com/,官方把仓库打包成一个小安装包,叫"release rpm",文件名形如 mysql57-community-release-el7-10.noarch.rpm。你装上它,它就会往 /etc/yum.repos.d/ 里写入 MySQL 专用的仓库配置,之后 yum install mysql-community-server 就能从官方仓库拉到真身。
挑版本是个高频坑点:官方仓库同时维护多个版本(比如 5.7 和 8.0),各自对应不同的 release 包。装之前务必先用命令看看自己的系统版本,尽量选和自己系统能力、和后面项目需求匹配的 MySQL 大版本:
cat /etc/redhat-release
# cat: 输出文件内容到屏幕
# /etc/redhat-release: 记录系统发行版信息的文件
# 输出样例: CentOS Linux release 7.8.2003 (Core) —— 说明这是 CentOS 7拿到 release 包文件(可以开机登录官方 http://repo.mysql.com/ 挑对应版本下载,也可以下载到本地再上传到服务器)后,用 rpm 把它装上。注意下面这个报错,几乎人人都会碰到:
rpm -Uvh mysql57-community-release-el7-10.noarch.rpm
# rpm: 底层包管理命令
# -U: upgrade, 有旧版则升级
# -v: verbose, 显示详细信息
# -h: 用 # 号显示安装进度
# 如果当前不是 root, 你会收到:
# error: can't create transaction lock on /var/lib/rpm/.rpm.lock (Permission denied)
# 意思是没有权限创建 rpm 的锁文件 —— 灵魂解法就是加 sudo看到 Permission denied 别慌,这纯粹是权限的问题,用 root 跑一次就行:
sudo rpm -Uvh mysql57-community-release-el7-10.noarch.rpm
# 正常会打印 headline:
# warning: ... Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
# 然后 Installing : mysql57-community-release-el7-10 ... [100%]
# 那个 NOKEY 警告只是提示"尚未导入这个签名公钥", 一般不影响安装, 后面我们专门处理装好之后,对比一下 /etc/yum.repos.d/ 目录。安装前长这样(一堆 CentOS- 开头的系统仓库文件):
ls /etc/yum.repos.d/ -al
# ls: 列出目录内容
# -a: all, 把隐藏文件(.开头的)也列出来
# -l: long format, 以"权限/属主/大小/日期"的详细格式展示
# 主要就是一堆 CentOS-*.repo / epel.repo / docker-ce.repo 之类的系统仓库安装后,这个目录里会多出两个 MySQL 专属文件:
ls /etc/yum.repos.d/ | grep mysql
# 安装后你会看到这两个新文件:
# mysql-community.repo —— MySQL 官方软件仓库的配置
# mysql-community-source.repo —— MySQL 官方源代码仓库的配置(一般不主动去用)
# 这俩就是"MySQL 官方 yum 源"落到磁盘上的真身仓库配置就位后,可以试着让 yum 列出和 mysql 相关的可用软件,检验一下"yum 是不是已经能看见官方 MySQL"了:
yum list | grep mysql
# yum list: 列出所有仓库里可安装的软件
# | grep mysql: 过滤出名字含 mysql 的
# 如果你能看到 mysql57-community-* 之类来自 mysql-community 仓库的包, 说明 yum 源配置成功小思考:
/etc/yum.repos.d/目录里其实装着一堆仓库(CentOS 自带、EPEL、docker-ce、还有我们新加的 mysql-community),为什么 yum 不会乱套、能分清该从哪个仓库下载哪个软件?详解:因为每个
.repo文件都定义了一个独立的仓库,仓库之间通过[仓库id]区段互相区分,每个区段里指定了自己的name、baseurl(下载地址)和enabled(是否启用)。安装mysql-community-server时,yum 会去所有"启用"状态的仓库里找这个包,而"mysql-community-*"开头的包只存在于 mysql-community 仓库里,所以 yum 能精确定位并发起下载。偶尔你会在日志里看到Repository epel is listed more than once in the configuration这类提示,那是多个仓库文件都声明了同一个仓库 id 导致的警告,一般不影响功能,但如果你洁癖重,可以检查下有没有重复定义的 epel 仓库文件去重一下。
三、用 yum 安装 MySQL 服务
yum 源配好了,"一键装服务"的重头戏就来了。安装 MySQL 的服务器和客户端,我们直接装重的那个 mysql-community-server(它会自动把依赖的公共模块、库、客户端也一起带上):
sudo yum install -y mysql-community-server
# yum install: 安装软件包
# -y: yes, 遇到中途的确认提示自动选"是", 免去手动回车
# mysql-community-server: 服务器端软件包
# 它会自动带上并安装这些组成部分:
# mysql-community-common —— 公共模块
# mysql-community-libs —— 共享库
# mysql-community-client —— 客户端(命令行工具 mysql)
# mysql-community-server —— 服务器(核心服务 mysqld)(如果这一步报错了,直接跳到文末"常见问题排查"那节,特别是有个和 GPG 密钥过期有关的报错,非常经典。)
装完你会发现,mysql 这个命令行客户端和 mysqld 这个数据库服务进程都齐了。接下来确认一下两个关键路径是否就位:
ls /etc/my.cnf
# 确认主配置文件存在。my.cnf 是 MySQL 的核心配置文件,
# 数据库端口、数据目录、字符集、socket、日志路径等都在这里调
sudo ls /var/lib/mysql
# 确认数据目录存在(里面现在应该已经有系统库的骨架结构)
# 这也是我们前面反复叮嘱要盯住的"数据落盘处"四、启动服务(systemctl)
软件装好了,但 MySQL 还没有"跑起来"。启动/停止/查看状态这类活儿,在 CentOS 7 里都是交给 systemctl 来做的。启动命令非常简单:
systemctl start mysqld.service
# mysqld: MySQL 的服务名, 注意是 mysqld(多了一个进程 daemon 的 d)
# systemctl start: 把 mysqld 服务启动起来
# 第一次 start 时 MySQL 会自动"初始化":
# 在 /var/lib/mysql 下生成系统库表和文件, 并生成一个临时 root 密码(稍后用)启动之后,怎么确认它真的起来了?最有说服力的办法是看进程:
ps ajx | grep mysqld
# 如果能看到一行包含 /usr/sbin/mysqld 的进程记录, 说明服务已经成功启动
# 那些文字像 "--daemonize --pid-file=/var/run/mysqld/mysqld.pid", 是服务以守护进程方式运行的标志以及一个更专业、更适合日常用的"服务健康自检"命令:
systemctl status mysqld.service
# systemctl status: 查看服务状态
# 如果显示 active (running), 说明服务正常运行;
# 显示 failed 则说明启动过程中出了岔子(比如 my.cnf 写错、端口被占)小思考:为什么我们启动的是
mysqld.service,而不是直接输入一个mysqld命令去跑?详解:
mysqld虽然是个可执行程序,但在生产环境我们从不"手动在前台敲个命令"去跑服务——那样服务会占住你的终端,终端一关服务跟着没,而且重启、开机自启、系统监控全都接不上。systemd(配合systemctl)是 CentOS 7 的"服务管家":你告诉它"给我把 mysqld 跑成后台守护进程",它就负责在后台拉起、替它管理生命周期、记录状态、还能设开机自启、崩溃自动重启。你俩的分工是:你只负责"声明要什么状态"(start/stop/restart/status),具体怎么拉后台的脏活累活,交给 systemctl 就行。这也解释了为什么排错前先systemctl status看状态,因为绝大多数"服务起不来"都能在这里一眼看到根因。
五、登录 MySQL 并初始化 / 修改 root 密码
服务起来了,接下来要"进线"。MySQL 跟 Linux 一样有个超级管理员,叫 root。但 MySQL 是个独立软件,它的 root 和 Linux 的 root 是两套独立的账号体系——MySQL 的 root 存在 MySQL 自己的数据目录(mysql.user 表)里,跟 Linux 系统用户毫无关系。我们要登录的是" MySQL 的 root"。
关键知识点:CentOS 7 上这套官方 yum 装的 MySQL 5.7,第一次初始化的时候会随机生成一个临时 root 密码,并且直接告诉你在日志文件里。所以第一件事是去日志里把它捞出来:
sudo grep 'temporary password' /var/log/mysqld.log
# sudo grep: 用 root 权限在文件里搜索匹配行
# /var/log/mysqld.log: MySQL 的服务日志文件
# 会输出一行形如:
# 2021-04-12T... A temporary password is generated for root@localhost: yLMalT:v+5l*
# 冒号后面的 "yLMalT:v+5l*" 就是你第一次登录要用的临时口令用这个临时密码登录 MySQL:
mysql -uroot -p
# mysql: 启动 MySQL 命令行客户端
# -u root: 以 root 用户身份登录
# -p: 提示输入密码(就是上面从日志里捞出来的临时密码)
# 看到进入 mysql> 提示符, 说明登录成功登录进来之后,第一步当然是改密码。但这里有个 5.7 特有的坑:MySQL 5.7 默认装了一个叫 validate_password 的密码强度插件,默认策略是"中"(policy=1),要求新密码必须同时包含数字、大小写字母、符号,且长度至少 8 位。你随便设个弱密码,它二话不说就拒绝。所以我们要么设一个强密码,要么(练习阶段图省事)先把校验关掉:
set global validate_password_policy=0;
# set global: 设置一个全局系统变量(本次运行期内生效)
# validate_password_policy: 密码强度校验策略, 0 表示只评"长度", 不再强制数字/大小写/符号set global validate_password_length=1;
# validate_password_length: 密码最小长度阈值, 设成 1 后, 长度>=1 即可通过校验
# (练习期方便, 生产环境请务必保持强密码策略)然后正式修改本地登录密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'qwer@wu.888';
# ALTER USER: 修改用户信息
# 'root'@'localhost': 指明要改的是"只在本地(localhost)登录的 root 用户"
# IDENTIFIED BY: 后面跟着新密码
# 注意结尾有分号, MySQL 语句以分号结尾FLUSH PRIVILEGES;
# 刷新权限缓存, 让刚才的密码/权限改动立即生效(老版本习惯; 新版本大多自动生效)到这里,本地登录这条链路就通了。退出后下次再用新密码登录就行了:
mysql -uroot -p
# 这回输入你刚改好的新密码即可要补充一个版本差异:如果你装的是比较新的 MySQL(比如 8.0 及以上,或某些构建版),它可能不生成临时密码,root 默认是没有密码的(或者说初始密码为空),你直接 mysql -uroot 回车可能就进去了,进去之后再补设密码即可。遇到这种情况别困惑,照着"直接试试能不能登录"这条思路走就行,我们文末会再提到判断技巧。
登录方法二:直接试试(无临时密码的场景)
对于"不生成临时密码"的新版本,最快的方法就是直接裸登录试一下:
mysql -uroot
# 不带 -p, 表示"我不提供密码, 先试试能不能进"
# 如果 root 初始为空密码, 这一下就能直接进到 mysql> 提示符
# 进去后建议立刻补一条 ALTER USER 把密码设上, 别让数据库裸奔碎片知识:临时密码到底在哪、为什么第一次登录非要看日志,这是很多新手卡死的点。请记住一个判断口诀:MySQL 5.7 走"临时密码派",密码写在
/var/log/mysqld.log;MySQL 8.0+ 走"默认空密码派",先把mysql -uroot试了再说。 二者的分水岭,就是观察初始化时有没有往日志里写temporary password那一行。
登录方法三:终极后备方案 —— skip-grant-tables
有的同学可能已经踩过了:日志里捞不到临时密码、直接登录又失败,进退两难。这时候还有一招"终极钥匙"——skip-grant-tables(跳过权限表)。它能让 MySQL 在启动时跳过权限校验,这样你用 root 就能无密码直接登进去,然后再去重置密码、把权限校验恢复回来。
来操作一遍。先编辑配置文件:
sudo vim /etc/my.cnf
# vim: 文本编辑器
# /etc/my.cnf: MySQL 主配置文件
# 在 [mysqld] 小节里(或干脆放到文件末尾)添加一行:
# skip-grant-tables
# 然后保存退出(vim 里 :wq 回车)加完这行,重启服务让配置生效:
systemctl restart mysqld
# systemctl restart: 重启服务, 等价于"先 stop 再 start"
# 这次启动跳过权限校验, root 可以直接登录登录进去:
mysql -uroot
# 由于已经 skip-grant-tables, 这次无需密码直接就进来了
# 你会看到: Welcome to the MySQL monitor. Commands end with ; or \g.进去之后,先手动刷新权限(把 skip 态下的权限表缓存加载真实化),再重置密码:
FLUSH PRIVILEGES;
# skip 模式下若不先执行这条, 直接改密码可能报错, 所以先刷新一把ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
# 把 root 本地密码重置成你自己的新密码FLUSH PRIVILEGES;
# 再次刷新, 确保改动落库并生效关键收尾,千万别忘:改完密码后,一定要回到配置文件把 skip-grant-tables 那行注释掉或删掉,再重启服务,让它恢复"需要密码、带权限校验"的正常状态:
sudo vim /etc/my.cnf
# 回到配置文件, 把刚才加的 skip-grant-tables 这行删掉(或行首加 # 注掉)systemctl restart mysqld
# 恢复权限校验, 下次就用自己的新密码正常登录了小思考:
skip-grant-tables是个很"顺手"的应急开关,但听说有安全隐患,它到底危在哪?详解:
skip-grant-tables会让 MySQL 跳过整个权限系统——任何能连上这个端口的连接,都以最高权限执行,等于"门锁全拆了"。所以它只配在"密码忘了、进不去了"这种紧急锁死场景临时用,且必须遵守纪律:用完立刻在配置里删掉这行并重启,别让它长期生效。更要命的是,如果此时你的 MySQL 还监听在对外网可访问的地址上(见下一节 bind-address),等于把这把"无锁的门"直接开给了互联网,任何人都能进来横冲直撞。另外注意:在 skip-tables 状态下你要能改密码,得先FLUSH PRIVILEGES一把,否则部分版本对ALTER USER会报"只能用它自己的访问方式"之类的错——这个顺序问题也很容易被忽略。
六、配置开机自启与 my.cnf 基础项
6.1 开机自启动
如果希望服务器一重启,MySQL 就自动跟着起来(数据库服务一般你肯定希望它开机自启),设置两下:
systemctl enable mysqld
# systemctl enable: 把服务注册进开机自启列表, 之后开机自动拉起systemctl daemon-reload
# 重新加载 systemd 的配置, 让刚才的自启设置立即生效/同步(开机自启这一步可设可不设——练习机上不设也不影响你现在使用,随手设上也行。)
小思考:
systemctl start和systemctl enable是不是一回事?能不能互相替代?详解:不是一回事,也不能替代。 它们管的是两件完全不同的事:
start是"现在立刻把它跑起来",只管当下这一次,效果在重启后自动消失;enable是"以后每次开机都自动拉起",管的是"未来",但它本身不会让当前这个服务立刻运行。所以最标准的组合是systemctl start(立即可用)+systemctl enable(开机自启)两条都做。这也回答了很多人"为什么 enable 了服务却没起来"的困惑——因为你只安排了它的"未来",没安排它的"现在"。
6.2 配置 my.cnf:字符集与存储引擎
MySQL 默认的字符集可能是 latin1 这类西欧字符集,存中文很容易出现乱码。为了让数据库、客户端、表都能优雅地处理中文,我们要在 my.cnf 里显式指定 UTF-8 编码。先看一眼默认配置长什么样:
cat /etc/my.cnf
# 里面通常已经有基础内容, 我们的任务是在 [mysqld] 小节补上字符集/存储引擎等关键项一个典型的最终配置形态是这样(在 [mysqld] 小节里)——你可以用 vim 打开后对号落座:
[mysqld]
port=3306 # 服务监听端口, MySQL 默认就是 3306
datadir=/var/lib/mysql # 数据目录, 落地所有数据库文件
socket=/var/lib/mysql/mysql.sock # 本地 socket 连接文件(本机免TCP连接用)
symbolic-links=0 # 禁止符号链接, 官方推荐的加固项, 防止符号链接带来的安全风险
log-error=/var/log/mysqld.log # 错误日志文件位置
pid-file=/var/run/mysqld/mysqld.pid # 服务进程 pid 文件的存放位置
character-set-server=utf8 # 服务端默认字符集, 指定 utf8, 让库表默认能存中文
default-storage-engine=innodb # 默认存储引擎, innodb 是支持事务/行锁的主流引擎配好后重启服务,让新配置生效:
systemctl restart mysqld
# 重启服务, 重新读取 my.cnf, 使字符集/存储引擎等配置生效教你一个排查思路:如果配置了
character-set-server=utf8后你发现终端里敲中文还是显示不出来(网上常说的"mysql 有 bug,汉字不回显"),先别急着乱改配置。优先检查你自己的终端环境变量是不是 UTF-8,用env | grep LANG看一眼:
env | grep LANG
# 期望看到 LANG=en_US.utf8 或类似含 utf8/UTF-8 的设置
# 如果是别的(比如 GBK、POSIX), 请先在系统/终端层面把语言环境切到 UTF-8,
# 再回头看 MySQL 客户端里的中文显示, 往往就正常了这一类的"显示乱"问题,根子常常不在 MySQL,而在"你的终端/系统外壳用什么编码来显示"——这个排查顺序值得背下来。
七、远程访问配置:放行 bind-address、账号 host 与防火墙
很多人装上 MySQL 后,发现只有服务器本机能连,别的机器(比如你自己电脑)就是连不上。这几乎是新手的最大瓶颈之一,我把它单独拎出来讲清楚。要把远程访问打通,其实要过三道关卡,每一关都别漏:
关卡一:服务器进程要监听在对外可见的地址上。
MySQL 在网上听命令的地方叫 bind-address。默认配置往往只监听在 127.0.0.1(本机环回地址),那么外面自然就连不进来了。放开它,让进程监听网卡的真实 IP(或全部网卡):
# 编辑 /etc/my.cnf 的 [mysqld] 小节, 加上或改成一行:
bind-address=0.0.0.0
# 0.0.0.0 表示"监听本机所有网卡地址", 这样外部网络才能连进来改完重启服务生效:
systemctl restart mysqld
# 重启使 bind-address 生效关卡二:MySQL 用户账号得允许从"远程主机"登录。
还记得 'root'@'localhost' 里的 localhost 吗?MySQL 的账号 = 用户名 + 登录来源主机,两者共同决定一个账号。'root'@'localhost' 只允许 root 从本机登录。要让 root 能从任意 IP 登录,就要创建一个 'root'@'%' 的账号(% 表任意主机):
mysql -uroot -p # 先正常登录进 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '你的密码';
# GRANT ALL PRIVILEGES: 授予全部权限
# ON *.*: 作用于所有库(* 通配)的所有表(*)
# TO 'root'@'%': 给"来自任意主机的 root"这个账号授权
# IDENTIFIED BY: 同时给这个远程账号设置密码(和本地密码保持一致更省心)FLUSH PRIVILEGES;
# 刷新权限, 让授权立即生效(如果你用的是 MySQL 8.0,GRANT ... IDENTIFIED BY 的旧语法被拆开了,得先 CREATE USER 再 GRANT,这点文末"常见问题"里提一句。)
关卡三:防火墙 / 安全组要放行 3306 端口。
即便账号、监听都放开了,CentOS 自带的 firewalld 防火墙默认是拦 3306 外访的。云服务器的话,还要留意云平台的安全组。本地 firewalld 放行:
sudo firewall-cmd --zone=public --add-port=3306/tcp --permanent
# firewall-cmd: firewalld 防火墙的命令行工具
# --zone=public: 区域设为公共区域
# --add-port=3306/tcp: 放行 TCP 的 3306 端口(mysql 默认端口)
# --permanent: 永久生效(而不是重启防火墙就失效)sudo firewall-cmd --reload
# 重新加载防火墙规则, 让刚才的放行立即生效三关都过了,从别的机器就能用如下命令连进来了(IP 换成你服务器的真实地址):
mysql -h 192.168.x.x -P 3306 -uroot -p
# mysql: 客户端
# -h 192.168.x.x: 指定要连的目标主机 IP
# -P 3306: 指定端口(默认就是3306, 大写的 P 才表示端口)
# -u root -p: 用 root 并提示输入密码小思考:远程确实连通了,但我这种"直接给 root 开
@'%'并放行全网0.0.0.0"的粗暴玩法,有没有更好的替代?详解:在学习/内网测试场景下,这种玩法图方便没大问题; 但放在公网生产环境就是大忌。一个 root 账号理论上能删库跑路,把 root 暴露到公网风险极高。更稳妥的做法是分层收敛:1) 别轻易给 root 开
@'%',尽量只对 root 保localhost,另建一个权限更窄的业务账号(比如'app'@'%',只GRANT给它需要的某个库);2) 绑定地址不必用全网0.0.0.0,可以只 bind 到你真正对外服务的那块网卡的 IP;3) 防火墙只对"你将要连接的那个来源 IP"放行 3306,而不是对全网开放。最小权限原则(只给够用的权限、只开够用的口子),是纵横数据库安全多年的第一性原理。
八、常见安装问题排查
这里汇集几个初学者最容易翻车的坑,都是我当年一路踩过来的,直接对着排:
问题一:yum 安装时碰到 GPG 密钥过期 / 签名失败
症状形如:
Failing package is: mysql-community-client-5.7.39-1.el7.x86_64
GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql这是 MySQL 官方老的 GPG 签名密钥过期了,yum 校验新包时对不上"旧公钥",于是拒绝安装。解法是导入官方最新发布的密钥再重装:
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
# rpm --import: 把指定 URL 的 GPG 公钥导入系统, yum 就能用它来校验官方新包
# 导入后重新执行 yum install -y mysql-community-server 即可通过为什么要 import 一个新密钥:MySQL 官方会不定期轮换签名用的 GPG 密钥(老 Key 到期后新包会用新 Key 签)。系统里还存着旧的公钥,就对不上号。把最新 key 拉进系统,yum 才能在装包时校验通过。这也顺带解释了你之前看到的那行
key ID 5072e1f5: NOKEY警告——它就是在提醒"这个包的签名我还没认过",认一下(import)就安静了。
问题二:服务起不来,systemctl status 显示 failed
最常见的两类根因:一是 my.cnf 里的配置项写错(比如路径不存在、缩进/格式错),导致 mysqld 一读配置就崩;二是 3306 端口或数据目录被占用(往往就是残留的 MariaDB 或上次没清干净的东西在捣乱)。排查三连:
systemctl status mysqld.service
# 看服务状态和最近失败原因sudo tail -n 50 /var/log/mysqld.log
# tail -n 50: 查看错误日志最后 50 行, 真正的失败原因基本都写在里面sudo netstat -tlnp | grep 3306
# netstat -tlnp: 查看正在监听(listen)端口的进程
# | grep 3306: 看看 3306 是不是被别的进程占着
# 发现被占就先把"旧主人"服务停掉, 再把占用释放出来问题三:装的是 MySQL 8.0,GRANT ... IDENTIFIED BY 报语法错
8.0 把"创建用户"和"授权"拆成了两条独立命令,不再支持在 GRANT 里顺带 IDENTIFIED BY'密码'。要分步写:
CREATE USER 'root'@'%' IDENTIFIED BY '你的密码';
# 先创建"允许任意主机登录的 root"这个账号并设密码GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
# 再给这个账号授权问题四:ALTER USER 报 ERR 或密码策略不通过
如果你没关策略插件就设弱密码,5.7 会用 validate_password 拦截你。要么按第一节那样调低策略(set global validate_password_policy=0; 等),要么设一个真正满足"数字+大小写+符号+8位"的强密码。生产环境请一律选后者。
九、思考题
到这里,一整套"装好 → 配好 → 远程能连"的流水线就跑通了。为了把今天的东西真正焊进脑子,下面几道思考题建议先自己动手想一遍,再对照答案。
思考题 1
为什么 CentOS 7 上我们非要用"官方 yum 源 + mysql-community-server"这套流程,而不是直接 yum install mysql?
详解:因为 yum install mysql 默认从 CentOS 的基础仓库里装,那里面提供的 MySQL 是在 CentOS 里重新打包的"兼容包",版本往往老旧、甚至和你想项目的 MySQL 版本对不上,后面做项目、跟官方文档对特性时容易出岔子。而我们第一手把这套流程装的是 MySQL 官方仓库的 mysql-community-server,版本新、和官方文档一致、后续 yum update 也能从官方渠道继续迭代。简言之:想装到什么版本的 MySQL、想和官方节奏同步,就该用官方 yum 源。这也呼应了挑 release 包时要"尽量选和自己系统版本、项目需求匹配的 MySQL 大版本"那句话。
思考题 2
systemctl start mysqld、systemctl enable mysqld、systemctl restart mysqld 三者分别在管什么?开机自启为什么不能只靠 start?
详解:start 管"现在",让当前这个服务立刻运行,但重启后会消失;enable 管"未来",把服务注册进开机自启清单,让每次开机自动拉起,但它不会立刻运行服务;restart 是"先 stop 再 start",用于"改了配置要重新加载"。开机自启之所以不能只靠 start,是因为 start 的效果只在"这一次开机期间"有效,重启后 systemd 并不会记住你刚才 start 过——自启是独立于 start 的另一套注册机制。所以要"现在就能用"再"开机还能自动起",start 和 enable 都要做。
思考题 3
'root'@'localhost' 和 'root'@'%' 是两个账号还是同一个?如果我只改了 'root'@'localhost' 的密码,远程能不能用新密码连上来?
详解:这是两个不同的账号。MySQL 的账号由"用户名 + 登录来源主机"两部分共同决定,'root'@'localhost'(仅限本机登录)和 'root'@'%'(允许任意主机登录)是两条独立的账号记录,各自的密码也独立设置。如果你只改了 'root'@'localhost' 的密码,那么远程(走的是 'root'@'%' 那条)用的依然是它自己的旧密码/权限,跟本地这条互不影响。这解释了为什么"改了本机密码,远程却连不上/用的还是旧密码"这类困惑——因为它们根本不是同一个账号。顺手把"远程连通要过三关(bind-address、账号 host、防火墙/安全组)"这个检查清单也一并记住。
思考题 4
skip-grant-tables 为什么必须"用完了就立刻删掉并重启"?如果它在 bind-address=0.0.0.0 的状态下长期开着,会有什么后果?
详解:skip-grant-tables 会让 MySQL 完全跳过权限校验,任何连接进来都以最高权限执行。它本是为了"密码忘了、进不去"而设的应急逃生门,不是日常配置。如果它一直开着,等于 MySQL 完全不设防;再叠加 bind-address=0.0.0.0(监听所有网卡)+ 防火墙放行 3306,这台数据库就等于把"无锁大门"对上了公网——任何人都能连上来自由操作,想读就读、想删就删,属于灾难级的安全裸奔。因此纪律必须严明:应急场景用,用毕立即注释/删除该行并 systemctl restart mysqld 恢复权限校验。另外在 skip 态改密码前要记得先 FLUSH PRIVILEGES,否则部分版本会拒绝 ALTER USER。
十、小结
到这里,我们完整走完了一条"从零到能连能用的" MySQL 安装全流程,把线程捋一捋:
卸载残留 → 装官方 yum 源 → 装 mysql-community-server → 用 systemctl 启动 → 从日志捞临时密码登录 → 关校验/改 root 密码 → (可选 skip-grant-tables 应急)→ 开机自启与 my.cnf 编码/引擎配置 → 远程连通三关(bind-address / 账号 host / 防火墙)→ 常见报错对症下药。
这一整套下来,你可能收获的不只是"服务器上多了一个 MySQL"。更重要的是你建立起了几条能复用一辈子的心智模型:
- 软件怎么装:yum 源把"去哪下、下哪版"讲清楚,剩下的交给 yum;
- 服务怎么管:start/enable/restart/status 是 systemd 的统一语言,排错从
systemctl status和日志入手; - 账号与权限:MySQL 账号由"用户 + 来源主机"共同决定,跨机器连接要先把"监听、账号、防火墙"三道关依次打通;
- 安全底线:临时逃生门(skip-grant-tables)用完即关,最小权限原则永远适用;动数据前先备份。
MySQL 有意思的地方在于,装好它只是"万里长征第一步"——接下来你还要学 CREATE DATABASE 建库、建表、写 SQL、做增删改查,去真正驱动它存储你的数据。而这些,正是后续文章要一件件讲的。等你已经把今天这套流程亲手敲过、把每个报错亲手排过,这第一座"承重墙"就立稳了。下一站,我们进入 MySQL 的数据库与表管理,去真正开始"用"它。
准备好了吗?
还没有评论 — 第一条由你来留。