14 KiB
tags, create time
| tags | create time | ||||
|---|---|---|---|---|---|
|
2026-05-16 00:00 |
MySQL 安装与初始化
概述
本文系统讲解 MySQL Community Edition 的安装部署和初始化配置,涵盖三种主流方式:Docker Compose(推荐开发环境)、YUM/RPM 包安装、通用二进制包安装。同时深入解析 my.cnf 配置文件的核心参数体系,以及 mysql_install_db 初始化时的底层行为。
[!TIP] 学习建议
- 初学者优先掌握 Docker Compose 方式,快速搭建可复现的开发环境;
- 运维/生产场景参考二进制安装流程,理解服务初始化的完整链条;
my.cnf参数部分按优先级阅读,先吃透 InnoDB 和网络两大块,日志和 Binlog 可在后续进阶时补充。思考题:为什么 InnoDB Buffer Pool 通常建议设为物理内存的 50%~70%,而不是 90%?(答案见下文 InnoDB 参数段落的注释)
Docker Compose 方式(推荐开发环境)
这是最轻量且可复现的方案,适合日常开发和 CI 测试。
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql-dev
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword # 首次启动自动创建 root 用户
MYSQL_DATABASE: app_db # 自动创建初始数据库
MYSQL_USER: app_user # 创建普通应用账户
MYSQL_PASSWORD: app_password # 该账户对 MYSQL_DATABASE 拥有完全权限
ports:
- "3306:3306" # 宿主机 3306 → 容器内 3306
volumes:
- ./init-db:/docker-entrypoint-initdb.d # 首次启动自动执行 SQL
- mysql-data:/var/lib/mysql # 持久化数据(容器删除后不丢失)
- ./my-custom.cnf:/etc/mysql/conf.d/my.cnf # 覆盖默认配置
command: >
--character-set-server=utf8mb4 # 统一字符集
--collation-server=utf8mb4_unicode_ci # 排序规则(不区分大小写)
--default-authentication-plugin=mysql_native_password # 兼容旧版客户端认证
--max-connections=500 # 最大并发连接数
--innodb-buffer-pool-size=256M # 开发机无需太大
volumes:
mysql-data:
启动与常用操作
docker compose up -d # 后台启动
docker compose down # 停止并移除容器(保留 volume)
docker compose logs -f # 查看实时日志
docker compose exec mysql mysql -u root -p # 进入容器内客户端
docker compose ps # 查看容器状态
docker compose restart # 重启(配置变更后适用)
[!QUESTION] 生产环境应该硬编码密码吗? 当然不。上述
docker-compose.yml中的明文密码仅适用于本地开发。 生产环境应使用 Docker Secrets、环境变量文件.env或密钥管理工具(如 HashiCorp Vault)来注入凭据。# .env 文件示例(加入 .gitignore!) MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASS} MYSQL_DATABASE=myapp_prodDocker Compose 会自动将
${VAR}替换为环境变量值。
init-db 目录妙用
docker-entrypoint-initdb.d/ 下只要是 .sql 或 .sh 脚本,会在数据库首次启动时按字母序自动执行:
| 文件类型 | 执行时机 | 典型用途 |
|---|---|---|
.sql |
首次初始化 | DDL建表、默认数据、权限分配 |
.sh |
首次初始化 | 调用 mysql CLI 执行动态逻辑 |
[!WARNING] 注意
- 容器已有数据时,init-db 脚本不会被重新执行。修改脚本后需删除 volume 重建:
docker compose down -v && docker compose up -d.sh脚本中若需连接 MySQL,务必等待 ready(可通过docker compose wait或健康检查机制)
二进制安装(生产环境参考)
对于需要精细控制的场景,官方推荐的两种方式:YUM/RPM 包适合标准发行版;通用二进制包提供最大灵活性。
方式一:YUM/RPM(CentOS / RHEL / Amazon Linux)
# 1. 下载 YUM 仓库配置(以 EL9 为例)
sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el9-3.noarch.rpm
# 2. 安装 MySQL Server
sudo yum install mysql-server -y
# 3. 启动服务并设置开机自启
sudo systemctl start mysqld
sudo systemctl enable mysqld
# 4. 获取临时 Root 密码(首次安装后打印到日志)
sudo grep 'temporary password' /var/log/mysqld.log
# 5. 安全加固(修改默认密码、移除匿名账户等)
sudo mysql_secure_installation
[!TIP] 临时密码在哪? MySQL 8.0 首次启动时会在
/var/log/mysqld.log中生成一个随机临时密码。 找到类似A temporary password is generated for root@localhost: xxxxxxxx的行,使用该密码登录mysql_secure_installation。
方式二:通用二进制包(跨发行版兼容)
适用于非标准发行版或需要自定义目录结构的场景:
# 1. 下载并解压(替换实际版本号)
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.xx-linux-glibc2.28-x86_64.tar.xz
tar -xvf mysql-8.0.xx-linux-glibc2.28-x86_64.tar.xz
sudo mv mysql-8.0.xx-linux-glibc2.28-x86_64 /usr/local/mysql
# 2. 创建专用系统用户(不建议用 root 运行 MySQL)
cd /usr/local/mysql
sudo groupadd mysql
sudo useradd -r -g mysql -s /bin/false mysql
# 3. 设置权限 + 初始化数据目录
sudo chown -R mysql:mysql .
sudo bin/mysqld --initialize --user=mysql --datadir=/data/mysql
# 4. 配置文件(可选,放在 /etc/my.cnf)
# 指定 basedir=/usr/local/mysql 和 datadir=/data/mysql
# 5. 初始化 SSL 证书(MySQL 8.0 必需)
sudo bin/mysql_ssl_rsa_setup --datadir=/data/mysql
# 6. 启动服务
sudo bin/mysqld_safe --user=mysql &
# 7. 验证登录
sudo bin/mysql -u root -p
[!QUESTION] caching_sha2_password vs mysql_native_password? MySQL 8.0 将默认认证插件从
mysql_native_password切换为caching_sha2_password:
- caching_sha2_password(新默认):更强的 SHA2 加密缓存机制,推荐所有新版客户端使用
- mysql_native_password(旧版):兼容性最好,老旧语言驱动可能不支持 SHA2
如果你的连接报
client does not support authentication protocol错误,临时解决方案是切换回旧版认证:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'new_password';但长期方案应是升级客户端库。
配置文件 my.cnf
配置文件加载优先级
MySQL 按以下顺序查找配置文件,后读取的覆盖先读取的(命令行参数始终最高):
graph LR
E["~/.my.cnf"] --> D["$MYSQL_HOME/my.cnf"]
D --> C["/etc/mysql/my.cnf"]
C --> B["/etc/my.cnf"]
B --> A["--defaults-file=<指定路径>"]
A --> F["命令行参数"]
F -.->|"最终生效"| Z["生效配置"]
[!NOTE] 关键理解
/etc/my.cnf通常是入口文件,内部可能!include其他目录;--defaults-file是唯一使用的配置文件,跳过所有默认路径(极少场景使用);- Docker 中常用
--config或conf.d/目录方式挂载自定义配置。
核心配置参数详解
MySQL 配置集中在 [mysqld] 段落下。按功能域分类如下:
网络
# ==================== 网络 ====================
port = 3306 # MySQL 默认端口
bind-address = 0.0.0.0 # 监听所有网卡(Docker 内用 127.0.0.1)
max_connections = 500 # 最大并发连接数
max_connect_errors = 1000000 # 同一主机连续中断次数上限,超限将被 block_host
字符集
# ==================== 字符集 ====================
character-set-server = utf8mb4 # 支持 emoji 的完整 UTF-8 实现
collation-server = utf8mb4_unicode_ci # 不区分大小写的排序规则
为什么用 utf8mb4 而非 utf8? MySQL 的 utf8 只支持最多 3 字节,无法存储 emoji;utf8mb4 才是标准 UTF-8(最长 4 字节)。
InnoDB 存储引擎
# ==================== InnoDB ====================
innodb_buffer_pool_size = 1G # 缓存数据和索引的物理内存占比
innodb_log_file_size = 512M # Redo Log 文件大小
innodb_flush_log_at_trx_commit = 1 # ACID 一致性级别控制
innodb_flush_method = O_DIRECT # 绕过 OS page cache,避免双重缓冲
innodb_file_per_table = 1 # 每张表独立 .ibd 文件
innodb_io_capacity = 2000 # SSD 建议调高,HDD 约 100~200
关键概念解释:
| 参数 | 原理 | 调整建议 |
|---|---|---|
innodb_buffer_pool_size |
InnoDB 的核心缓存区域,存放数据页和索引页 | 物理内存的 50%~70%——为 OS 和其他进程预留空间,占满 90% 反而导致性能下降 |
innodb_log_file_size |
Redo Log 保证持久性(WAL 机制) | 越大容纳未刷盘事务越多,但重启恢复越慢;512M 是通用起点 |
O_DIRECT |
直接 I/O 模式 | 启用后 MySQL 自己管理 Buffer Pool,不再经过 OS Cache(避免双重缓冲浪费) |
慢查询日志
# ==================== 日志 ====================
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_error = /var/log/mysql/error.log
使用方式: 启用后可以通过 mysqldumpslow 分析或直接用文本工具查看超时查询:
# 找出执行时间最长的 10 条
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 实时追踪慢查询(运维调试利器)
tail -f /var/log/mysql/slow.log
Binlog(二进制日志)配置
Binlog 是 MySQL 最核心的日志类型,用于主从复制和数据恢复:
# ==================== Binlog ====================
server_id = 1 # 集群内唯一标识(1~2^32-1)
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW # 记录每一行变更明细
binlog_expire_logs_seconds = 604800 # 7 天后自动清理
max_binlog_size = 100M # 单文件上限(实际可能略超)
gtid_mode = ON # 全局事务 ID,简化主从切换
enforce_gtid_consistency = ON # 只允许 GTID 安全的事务
[!TIP] Binlog Format 对比
格式 内容 优点 缺点 STATEMENT 原始 SQL 文件小,审计直观 函数调用可能导致主从不一致 ROW(推荐) 每行变更前后值 数据一致性最强 文件较大 MIXED 混合模式 兼顾两者 逻辑复杂,难以预测 结论:生产环境统一用
ROW,现代磁盘成本已不再是瓶颈。
[!QUESTION] innodb_flush_log_at_trx_commit 怎么选?
值 行为 丢失数据风险 性能 1 每次事务 commit 都刷盘 零(ACID 完全符合) 最低 2 每次 commit 写入 OS 缓存,每秒刷盘 系统断电丢失 < 1 秒 高 0 每秒都写并刷盘,commit 仅写入缓冲区 可能丢多秒数据 最高 建议:金融/支付类业务必须用 1;内容类业务可以用 2 换取性能提升。
mysql_install_db 初始化原理
当首次启动 MySQL(或手动执行 mysql_install_db)时,底层会完成以下几件事:
flowchart TD
S["mysqld 启动"] --> I["数据目录检查"]
I -->|为空| D["执行 mysql_install_db"]
I -->|非空| C["跳过初始化,直接加载现有数据"]
D --> A["创建系统数据库"]
A --> A1["mysql schema — 用户权限、角色、插件"]
A --> A2["sys schema — 性能分析视图集合"]
A --> A3["performance_schema — 运行时指标采集"]
A --> A4["information_schema — SQL 元数据虚拟表"]
A --> B["创建管理员账户"]
B --> B1["root@localhost — 超级管理员"]
B --> B2["使用 caching_sha2_password 认证"]
A --> E["写入其他系统文件"]
E --> E1["ibdata1 — InnoDB 系统表空间"]
E --> E2["auto.cnf — Server UUID"]
C --> F["加载 my.cnf 配置并监听端口"]
逐段拆解:
| 步骤 | 说明 | 常见关联问题 |
|---|---|---|
| 创建 system schemas | mysql 存权限,performance_schema 供性能监控,information_schema 是 SQL 标准提供的元数据字典 |
删了这些库会导致实例无法正常运行 |
| 创建 root 账户 | 8.0 不再允许匿名访问 test 库;密码通过临时日志输出而非自动设为空 |
忘记临时密码 → 删除 data dir 重新初始化 |
| 初始化 InnoDB 表空间 | ibdata1 存放系统表和 undo log;ib_logfile* 是 Redo Log(两份互为镜像) |
Redo Log 损坏 → 实例无法启动 |
| 写入 auto.cnf | 包含唯一的 Server UUID,主从复制和 GTID 依赖此标识 | 克隆虚拟机未重置 UUID → 主从冲突 |
数据目录结构
初始化完成后,数据目录的组织方式如下:
/var/lib/mysql/ (datadir 根目录)
├── ibdata1 # InnoDB 系统表空间(存放系统表 + undo log)
├── ib_logfile0 # Redo Log 文件 1
├── ib_logfile1 # Redo Log 文件 2(与 1 互为镜像)
├── auto.cnf # Server UUID(UUID 不变,主从复制不冲突)
├── mysql/ # 系统数据库(user, role, db, columns_priv 等 .ibd 文件)
├── performance_schema/ # 运行时性能数据采集
├── sys/ # 基于 performance_schema 的友好视图
├── app_db/ # 每个用户数据库一个目录
│ ├── users.ibd # 单表独立表空间(innodb_file_per_table=1)
│ └── orders.ibd
└── relay-log.index # 主从复制的中继日志索引(仅作为 replica 时存在)
关联笔记
- hhs/Redis/01-安装与部署 — Redis 的安装方式与 MySQL 对比
- hhs/EXAM/Week05 — Docker Compose 多服务编排示例
- hhs/DEV/Go-Database — Go 驱动连接 MySQL 的参数配置