Appearance
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-serverUbuntu/Debian:
bash
apt update
apt install -y mysql-server确认版本:
bash
mysql --version
mysqld --version包安装后文件散落在系统各个位置,几个常见路径要知道:/etc/my.cnf(RHEL 系配置入口)或 /etc/mysql/my.cnf(Debian/Ubuntu)、/var/lib/mysql(默认数据目录)、/var/log/mysqld.log(RHEL 系错误日志)或 /var/log/mysql/error.log(Debian/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/mysqluseradd -r 创建系统账号(UID 在系统账号范围),-s /sbin/nologin 表示这个账号不能登录 shell——MySQL 进程用这个身份运行,不需要人登录。数据目录里放着 InnoDB 表空间文件、系统库表、undo 表空间等关键数据,目录权限要收紧,不能随便给人读。
几个和数据、日志相关的概念,后面备份复制都会用到,先理清:
| 对象 | 在哪 | 干什么 |
|---|---|---|
| 数据目录(datadir) | datadir 参数指定 | 存表空间、系统库(mysql/sys)、undo 表空间 |
| 错误日志 | log_error 参数指定 | 记录启动失败、崩溃恢复、复制异常、权限错误 |
| binlog | log_bin 参数指定 | Server 层逻辑变更日志,用于复制和时间点恢复 |
| redo log | InnoDB 内部日志 | 记录已提交事务需要重放的页变更,用于崩溃恢复 |
| undo log | InnoDB undo 表空间 | 支持事务回滚和 MVCC 读取历史版本 |
binlog 和 redo 的职责不同,别搞混:binlog 记录的是"某条 SQL 提交了",是 Server 层的;redo 记录的是"某个数据页被改了",是 InnoDB 引擎层的。崩溃恢复靠 redo,复制和按时间点恢复靠 binlog——两者放在一起并不能互相替代。这个区分是理解 MySQL 复制和恢复的基础。
初始化数据目录:
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 是复制拓扑里给每个实例的唯一编号(重复会导致复制异常,就算单机也先写上);character_set_server=utf8mb4(MySQL 里的 utf8 不是完整 UTF-8,新库都用 utf8mb4,这点特别容易踩坑);innodb_buffer_pool_size 是内存规划的核心参数,影响查询到底是读内存还是读磁盘;log_bin 开启 binlog(不开就无法做时间点恢复,也无法搭主从);binlog_format=ROW(行格式 binlog,复制和回放更精确,少一些语句级歧义)。
innodb_flush_log_at_trx_commit=1 和 sync_binlog=1 这两项经常放在一起讨论,叫"双 1"。前者关注 redo 刷盘(每次提交都刷 redo 到磁盘,防止宕机后"事务提交了但日志没落盘"),后者关注 binlog 刷盘(每次事务都同步 binlog 到磁盘)。两者配套,确保 redo 和 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 mysqldLimitNOFILE 这里有个坑:它设置进程可以打开的句柄数上限,MySQL 的连接数、表数量、binlog 文件数量都消耗文件描述符——默认的 systemd 限制(通常 1024 或 4096)不一定够。如果 open_files_limit 配大了但 systemd 这边限制小,实际生效的会是两边的较小值。所以两边都要设,不然 MySQL 侧的配置白搭。
六、首次登录和改密码
包安装后的临时 root 密码写在错误日志里:
bash
grep 'temporary password' /var/log/mysqld.log用临时密码登录,然后立刻改掉:
bash
mysql -uroot -psql
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPassword_123!';确认当前身份:
sql
SELECT USER(), CURRENT_USER();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.sockMySQL 的配套工具:mysql 是交互式客户端执行 SQL、mysqladmin 做 ping/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 密码(从临时密码改成强密码)、删匿名用户(匿名用户可以无密码连接)、不开放远程 root(root 只保留 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 混用——这是数据库安全的基本原则。