Skip to content

MySQL 安装与基础

MySQL 运维的第一步是把实例装起来、配置好、能正常启停和连接。后续的备份恢复、主从复制、性能排查,都建立在"这个实例能正常跑"的基础上。

一、版本和部署方式的选择

现在生产环境里最常见的是 MySQL 8.0,也有一些 5.7 的存量环境。如果没有历史包袱(老应用必须用 5.7 的某些特性),新环境通常直接选 8.0 LTS 或者发行版/云厂商提供的稳定版本。

几种部署方式各有适用场景:

方式适合什么场景要注意什么
系统包安装(yum/apt)测试环境、单机使用版本受仓库限制,不一定是最新版
官方 Yum/Apt 仓库自建标准化环境版本相对可控,但要注意不同小版本的变化
二进制包离线部署、固定版本号不能变目录结构、systemd 都要自己处理
源码编译需要特殊编译参数维护成本高,一般情况下不优先选
容器部署测试、开发、K8s 环境数据目录和配置的持久化要处理好,否则容器重启数据就没了

生产 MySQL 的安装来源尽量统一。用系统包装了一半又手工覆盖一半,后面升级和排查会找不到到底用的是哪个版本的哪个包。

二、包安装

RHEL/Rocky/CentOS 通常先配 MySQL 官方仓库再安装:

bash
yum install -y https://repo.mysql.com/mysql80-community-release-el8.rpm
yum install -y mysql-community-server

Ubuntu/Debian:

bash
apt update
apt install -y mysql-server

确认版本:

bash
mysql --version
mysqld --version

包安装后文件分布在系统各个位置,常见的:

路径是什么
/etc/my.cnfRHEL 系配置文件入口
/etc/mysql/my.cnfDebian/Ubuntu 配置文件入口
/var/lib/mysql默认数据目录
/var/log/mysqld.logRHEL 系错误日志
/var/log/mysql/error.logDebian/Ubuntu 错误日志
/usr/sbin/mysqld服务端程序
/usr/bin/mysql客户端程序

不同发行版和安装源的路径可能有差异,查具体文件位置:

bash
rpm -ql mysql-community-server | head    # RHEL 系
dpkg -L mysql-server | head              # Debian 系

三、二进制包部署

二进制包适合需要固定版本和离线部署的场景。解压、建用户、规划目录三步走:

bash
tar -xf mysql-8.0.x-linux-glibc2.28-x86_64.tar.xz -C /usr/local/
ln -s /usr/local/mysql-8.0.x-linux-glibc2.28-x86_64 /usr/local/mysql

创建 MySQL 专用的系统用户和数据目录:

bash
groupadd mysql
useradd -r -g mysql -s /sbin/nologin mysql

mkdir -p /data/mysql/{data,logs,tmp}
chown -R mysql:mysql /data/mysql

useradd -r 创建系统账号(UID 一般在系统账号范围),-s /sbin/nologin 表示这个账号不能登录 shell——MySQL 进程用这个身份运行,不需要人登录。

数据目录里面放着 InnoDB 表空间文件、系统库表、undo 表空间等关键数据。目录权限要收紧,不能随便给人读。

几个和数据、日志相关的概念,后面备份复制都会用到:

对象在哪干什么用
数据目录(datadir)datadir 参数指定存放表空间、系统库(mysql/sys 等)、undo 表空间
错误日志log_error 参数指定记录启动失败、崩溃恢复、复制异常、权限错误
binloglog_bin 参数指定Server 层逻辑变更日志,用于复制和时间点恢复
redo logInnoDB 内部日志记录已提交事务需要重放的页变更,用于崩溃恢复
undo logInnoDB undo 表空间支持事务回滚和 MVCC 读取历史版本

binlog 和 redo 的职责不同:binlog 记录的是"某条 SQL 提交了",是 Server 层的;redo 记录的是"某个数据页被改了",是 InnoDB 引擎层的。崩溃恢复靠 redo,复制和按时间点恢复靠 binlog。两者放在一起并不能互相替代。

初始化数据目录:

bash
/usr/local/mysql/bin/mysqld \
    --initialize \
    --user=mysql \
    --basedir=/usr/local/mysql \
    --datadir=/data/mysql/data

--initialize 会创建系统表空间、系统库(mysql 库)、生成初始 root 密码,并把临时密码写到错误日志里。这个命令只在第一次使用时执行——重新 --initialize 会让已有数据全部丢失。

四、配置文件

一份最小但完整的配置,把几个核心要素都写清楚:

ini
[mysqld]
server_id=1
port=3306
user=mysql
basedir=/usr/local/mysql
datadir=/data/mysql/data
socket=/data/mysql/tmp/mysql.sock
pid-file=/data/mysql/tmp/mysqld.pid
log_error=/data/mysql/logs/error.log

character_set_server=utf8mb4
collation_server=utf8mb4_0900_ai_ci

max_connections=500
open_files_limit=65535

innodb_buffer_pool_size=1G
innodb_flush_log_at_trx_commit=1
sync_binlog=1

log_bin=/data/mysql/logs/mysql-bin
binlog_format=ROW
binlog_expire_logs_seconds=604800

每个参数解决什么问题:

参数干什么为什么要注意
server_id复制拓扑里给每个实例唯一编号重复会导致复制异常,就算单机也先写上
datadir数据目录位置改到已有目录前要确认里面没有旧实例的数据
character_set_server=utf8mb4默认字符集MySQL 里的 utf8 不是完整 UTF-8,新库都用 utf8mb4
innodb_buffer_pool_sizeInnoDB 缓冲池大小内存规划的核心参数,影响查询到底是读内存还是读磁盘
log_bin开启 binlog不开启就无法做时间点恢复,也无法搭主从
binlog_format=ROW行格式 binlog复制和回放更精确,少一些语句级歧义
innodb_flush_log_at_trx_commit=1每次提交都刷 redo 到磁盘防止宕机后"事务提交了但日志没落盘"
sync_binlog=1每次事务都同步 binlog 到磁盘和上面那条配套,确保 redo 和 binlog 都落盘了再告诉客户端"提交成功"

这两项是常放在一起讨论的。innodb_flush_log_at_trx_commit=1 关注的是 redo 刷盘,sync_binlog=1 关注的是 binlog 刷盘。核心业务库一般保持双 1,优先保证数据安全。写入量特别大的场景,再根据磁盘能力和可接受的数据丢失窗口来评估是否调低。

配置文件改完之后的确认:MySQL 没有完全等价于 nginx -t 的配置检查命令,通常靠重启实例来验证。所以生产上改配置前备份旧配置,改完之后在低峰窗口重启观察。

五、systemd 管理

包安装通常自带 systemd unit:

bash
systemctl enable mysqld
systemctl start mysqld
systemctl status mysqld --no-pager

二进制部署需要手写 unit 文件,保存为 /etc/systemd/system/mysqld.service

ini
[Unit]
Description=MySQL Server
After=network.target

[Service]
Type=forking
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf
ExecStop=/usr/local/mysql/bin/mysqladmin --defaults-file=/etc/my.cnf shutdown
LimitNOFILE=65535
Restart=on-failure
PrivateTmp=false

[Install]
WantedBy=multi-user.target

保存后加载并启动:

bash
systemctl daemon-reload
systemctl enable mysqld
systemctl start mysqld

LimitNOFILE 设置进程可以打开的句柄数上限。MySQL 的连接数、表数量、binlog 文件数量都消耗文件描述符——默认的 systemd 文件描述符限制(通常 1024 或 4096)不一定够。如果 open_files_limit 配置大了但 systemd 这边限制了,实际生效的会是两边的较小值。

六、首次登录和改密码

包安装后的临时 root 密码写在错误日志里:

bash
grep 'temporary password' /var/log/mysqld.log

用临时密码登录,然后立刻改掉:

bash
mysql -uroot -p
sql
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPassword_123!';

确认当前身份:

sql
SELECT USER(), CURRENT_USER();

USER() 返回的是客户端声称的用户名和来源地址,CURRENT_USER() 返回的是 MySQL 最终匹配到的授权账号。排查权限问题时,后者更关键——你以为连的是 root@localhost,实际可能被匹配成了 root@%

七、常用客户端和管理命令

连接方式:

bash
# TCP 连接
mysql -h 127.0.0.1 -P 3306 -uroot -p

# 本地 socket 连接(不经过 TCP)
mysql -uroot -p --socket=/data/mysql/tmp/mysql.sock

MySQL 的配套工具:

工具干什么用
mysql交互式客户端,执行 SQL
mysqladminping、shutdown、status 等管理操作
mysqldump逻辑备份,导出 SQL
mysqlbinlog查看和回放 binlog 内容
mysqlshow快速看有哪些库、表

检测实例是否活着:

bash
mysqladmin -uroot -p ping

查看关键变量和状态:

sql
SHOW VARIABLES LIKE 'datadir';
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'character_set_server';

SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Uptime';

八、目录和日志确认

先知道关键路径在哪:

sql
SHOW VARIABLES WHERE Variable_name IN (
  'datadir',
  'log_error',
  'general_log_file',
  'slow_query_log_file',
  'socket'
);

错误日志是排查的第一现场——启动失败、崩溃恢复、复制错误、权限错误都会写在这里:

bash
tail -n 100 /data/mysql/logs/error.log

确认端口和进程:

bash
ss -lntp | grep ':3306'
ps -ef | grep '[m]ysqld'

grep '[m]ysqld' 的技巧是方括号让正则匹配 m 而不是字面字符串 [m],这样 grep 自己的命令行不会出现在结果里。

九、装完之后的基础安全处理

新装 MySQL 至少处理这几项:

做什么怎么处理
改 root 密码从临时密码改成强密码
删匿名用户匿名用户可以无密码连接
不开放远程 rootroot 只保留 localhost 来源
删 test 库默认创建的 test 库权限较宽,生产不需要
确认 binlog 开启为后续备份恢复和复制做准备
确认错误日志路径和权限保证日志能正常写入

对应的 SQL:

sql
SELECT user, host FROM mysql.user;             -- 先看有哪些账号
DROP USER IF EXISTS ''@'localhost';             -- 删除匿名用户
DROP DATABASE IF EXISTS test;                   -- 删除 test 库
FLUSH PRIVILEGES;

正式环境的 root 通常只保留本机 socket 登录。应用账号按库、按最小需要的权限来建,不和 root 混用。