Skip to content
安装与配置

安装与配置

解决"把 MySQL 8.4 装起来、配起来、连得上"这一件事:版本与发行版选型、Windows/Linux/Docker 三条安装路径、首次登录的安全初始化、数据目录布局与 my.cnf 必配参数速查。装完之后遇到乱码、连不上、重启丢数据这类怪事,先翻第 10 节。


1. 版本与发行版选择

1.1 先看清版本演进线

Oracle 在 2024 年前后把 MySQL 的版本节奏换了挡,选版本之前先弄清楚自己在跟哪条线:

  • 8.0(2018-04 GA,存量最新 8.0.46):生产存量的绝对主力,但 2026-04-21 起转入 Oracle Sustaining Support——官方 EOL 通知原文 “as of April 21, 2026, MySQL 8.0 is covered under Oracle Sustaining Support”,即不再有常规补丁/安全更新节奏,官方建议升级到 8.4 LTS 或 9.7 LTS。
  • 8.4 LTS(2024-04,当前 8.4.13):长期支持线,本手册的主基线。
  • 9.0 ~ 9.6(2024-07 起的 Innovation 序列):半年一个创新版,充当功能试验田;9.0 引入了 VECTOR 数据类型。9.7 升格为 LTS(当前 9.7.2,官方下载页实测标注),与 8.4 并列为两条受支持的 LTS 线。
  • 2026-07 起切换日期式版本:MySQL 26.7(2026-07)、26.10(2026-10,官方下载页当前最新)。26.x 仍是 Innovation(季度发布),不是 LTS,不要直接上生产;细节本手册不展开。

本手册写作基线:主线 8.4 LTS(8.4.13 为参照补丁,参数面与 SQL 语义和 8.0 基本一致、两者对照;8.4 主要是清理了一批弃用特性,比如默认禁用 mysql_native_password,见第 10 节);9.7 LTS 是新部署的可选项——8.0.30+ 的参数与特性在 9.7 全部可用,另含 9.x 引入的 VECTOR 类型等。手册事实以 8.4 为准,选 9.7 时差异对照官方 release notes 即可。

生产选型直接说结论:

  • 新立项在 8.4 LTS(资料最全、用户基数最大)与 9.7 LTS(需要 VECTOR 等新特性)里二选一,都不用半年一升。
  • 存量 8.0 自 2026-04-21 进入 Sustaining Support,不再随节奏收安全补丁——“继续跑"不再是可持续的说法,升级到 8.4 / 9.7 应排进日程;跨大版本升级前先跑升级检查(第 9 节)。
  • 26.x 创新版季度线只用于预览新特性,生产不要碰。

1.2 Community / Percona / MariaDB

三家都是 MySQL 血统,但差异不是"换个皮肤”,尤其最后一条:

发行版 维护方 关键差异 适合场景
MySQL Community Oracle 官方参考实现;审计、防火墙、线程池等企业特性在 Enterprise 版 默认选择,文档与行为最权威
Percona Server Percona 协议兼容 MySQL,附带增强(Performance Schema 采样、快速补丁节奏),同源的 xtrabackup、Percona Toolkit 工具链成熟 需要开源增强工具链、要更快的安全更新
MariaDB MariaDB 基金会 与 MySQL 已实质性分叉,不是替代品,见下 只建议延续已有 MariaDB 技术栈

注意:MariaDB 不是"MySQL 的另一个版本号"。两边的 GTID 格式完全不同(MariaDB 是 domainId-serverId-seq,MySQL 是 uuid:seq),复制协议互不兼容;MariaDB 的 JSON 是 LONGTEXT + CHECK 约束而非真 JSON 类型;优化器、大量参数名、8.0 引入的 caching_sha2_password、CTE 与窗口函数的部分语法细节都各自演化。把两者当同一事物做迁移,是过去十年代价最高的认知错误之一。本手册全部内容默认 MySQL(Percona Server 可直接套用),不覆盖 MariaDB。

安装源同理:第 3 节同时给 MySQL 官方源与 Percona 源,两者不要混装到同一台机器,仓库冲突时卸干净再换。


2. Windows 安装(zip 免安装)

Windows 推荐 zip 免安装版:MSI 安装器把路径写死、卸载残留多,zip 版目录自己定、干净可控。开发机用 zip,生产 Windows(少见)同理。

2.1 准备

  1. 从 https://dev.mysql.com/downloads/mysql/ 选 8.4.x、平台 Windows,下载 Zip Archive(x86 64-bit)。
  2. 解压到不含中文、不含空格的路径,例如 C:\mysql-8.4。

路径含中文(如 D:\数据库\mysql)是第 10 节踩坑清单的第一条:轻则初始化失败,重则服务能起但日志编码一塌糊涂。别在这上面试探运气。

2.2 配置文件 my.ini

新建 C:\my.ini:

[mysqld]
basedir=C:/mysql-8.4
datadir=C:/mysql-8.4/data
port=3306
character_set_server=utf8mb4
collation_server=utf8mb4_0900_ai_ci
default-time-zone='+08:00'
lower_case_table_names=1

[client]
port=3306
default-character-set=utf8mb4

两个容易忽略的细节:路径里的正斜杠 / 在 Windows 上同样被接受,省掉反斜杠转义;文件必须保存为无 BOM 的编码(记事本选 ANSI,或 VS Code 选 UTF-8 无 BOM),带 BOM 的 my.ini 会让 mysqld 解析异常。lower_case_table_names 必须在初始化前定死,原因见第 10 节第 4 条。

2.3 初始化、注册服务、启动

用管理员命令提示符执行:

# 1) 初始化数据目录。data 目录必须不存在或为空,否则报错
#    --initialize-insecure:root 空密码,仅限本机开发
"C:\mysql-8.4\bin\mysqld" --defaults-file=C:\my.ini --initialize-insecure --console

# 2) 注册 Windows 服务,服务名 MySQL84
"C:\mysql-8.4\bin\mysqld" --install MySQL84 --defaults-file=C:\my.ini

# 3) 启动服务
net start MySQL84

# 4) 登录(空密码回车)并设置 root 密码
"C:\mysql-8.4\bin\mysql" -uroot
ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPwd#2026';

--initialize-insecure 与 --initialize 的区别:后者给 root 生成一个随机临时密码写进错误日志,首次登录必须先改密。个人开发机用前者方便,任何别人能摸到的机器都用后者。

把 C:\mysql-8.4\bin 加入系统 PATH,否则每条命令都要写全路径。卸载服务用 "...\bin\mysqld" --remove MySQL84。

2.4 验证

SELECT VERSION(), @@datadir, @@character_set_server, @@lower_case_table_names;
-- 8.4.13    C:/mysql-8.4/data/    utf8mb4    1

3. Linux 安装

生产 Linux 一律走包管理器;除非要做定制移植,否则不要下 tar.gz 手工装。

3.1 Debian / Ubuntu(官方 APT 源)

# 下载并安装 apt 配置包(具体版本号以官网当前为准)
wget https://dev.mysql.com/get/mysql-apt-config_0.8.3x-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.3x-1_all.deb   # 弹出的 ncurses 界面里选 8.4 LTS
sudo apt update
sudo apt install mysql-community-server
sudo systemctl enable --now mysql

DEB 安装过程会交互式要求设置 root 密码并选择默认认证插件,选默认的 caching_sha2_password。

注意:MySQL APT 仓库的签名密钥过期是这个源历史上最著名的一次全局故障(2023 年那次让海量机器 apt update 直接报 NO_PUBKEY / signatures couldn't be verified)。遇到时重新下载最新 mysql-apt-config 包安装,或按官网指引导入新 key 指纹,不要盲目 apt-key 兜圈子。

3.2 RHEL / Rocky / AlmaLinux(官方 YUM 源)

sudo dnf install https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm
# RHEL/Rocky 8 需要先禁用自带的 mysql 模块;EL9 可跳过
sudo dnf module disable mysql
sudo dnf install mysql-community-server
sudo systemctl start mysqld

# RPM 安装:首次启动自动初始化并给 root 生成临时密码,从错误日志里取
sudo grep 'temporary password' /var/log/mysqld.log
mysql -uroot -p'<临时密码>'
-- 临时密码带"过期"属性,不改密什么都干不了(报 ERROR 1820),先改密
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Mysql#2026Root!';

3.3 Percona Server 源

sudo dnf install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
sudo percona-release enable-only tools ps-80   # 仓库频道命名以 percona-release 文档为准
sudo dnf install percona-server-server percona-toolkit

Percona Server 与 MySQL 协议兼容,本手册内容通用;选它的实际动机通常是 xtrabackup 热备份和 Percona Toolkit(pt-online-schema-change、pt-query-digest,见 09-Online-DDL与大表变更.md、08-EXPLAIN与查询优化.md)。

3.4 通用收尾

systemctl enable mysql    # 或 mysqld,RPM/DEB 服务名不同,别背,用 systemctl 列出来看
ss -lntp | grep 3306
mysqladmin -uroot -p status

4. Docker 部署

本地开发首选容器,五分钟起一个实例;生产容器化(K8s StatefulSet)的存储与高可用思路见 10-主从复制与高可用.md,这里只保证"跑起来且不丢数据"。

4.1 单实例

docker run -d --name mysql84 \
  -e MYSQL_ROOT_PASSWORD='Root_2026#pwd' \
  -p 3306:3306 \
  -v /srv/mysql84/data:/var/lib/mysql \
  -v /srv/mysql84/conf.d:/etc/mysql/conf.d \
  mysql:8.4

要点逐条说清:

  • -v ...:/var/lib/mysql 必须挂。容器的可写层不是持久存储,docker rm 之后数据一起消失——这是 Docker 场景第一大事故(第 10 节第 3 条)。
  • 配置写进挂载目录下的 .cnf 文件(如 conf.d/mine.cnf),不要试图用单个文件覆盖镜像里的 /etc/mysql/my.cnf 本体。
  • 官方镜像用 MYSQL_ROOT_PASSWORD 初始化时,root 的 host 默认较宽(镜像提供 MYSQL_ROOT_HOST 变量控制,默认值行为以镜像文档为准),和裸装"root 只能 localhost"不同。公网机器上别这么裸跑。
  • 容器时区默认 UTC,SELECT NOW() 和宿主机差 8 小时:在 conf.d 里写 default-time-zone='+08:00'(或给容器加 TZ=Asia/Shanghai 并确认镜像带 tzdata)。
  • 绑定挂载的宿主机目录若报 Permission denied,是容器内 mysql 用户(uid 999)写不了:改用命名卷,或把目录属主交给该 uid。

进容器操作:

docker exec -it mysql84 mysql -uroot -p --default-character-set=utf8mb4

4.2 一主一从(docker compose 示例)

目的只是把"双实例 + 复制"的骨架跑通,复制原理与运维细节在 10-主从复制与高可用.md 展开。

services:
  mysql-master:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: 'Root_2026#pwd'
    command:
      - --server-id=1
      - --gtid-mode=ON
      - --enforce-gtid-consistency=ON
    ports: ["3306:3306"]
    volumes:
      - master-data:/var/lib/mysql

  mysql-replica:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: 'Root_2026#pwd'
    command:
      - --server-id=2
      - --gtid-mode=ON
      - --enforce-gtid-consistency=ON
      - --read-only=ON
      - --super-read-only=ON
    ports: ["3307:3306"]
    volumes:
      - replica-data:/var/lib/mysql

volumes:
  master-data:
  replica-data:

8.0 起 binlog 默认开启,这里不用显式写 --log-bin;super_read_only 连 root 的写也挡掉,是从库的标配保险。

初始化复制(8.0.23+ 的新语法 CHANGE REPLICATION SOURCE TO,CHANGE MASTER TO 已在 8.0 弃用):

# 主库建复制账号
docker exec mysql-master mysql -uroot -p'Root_2026#pwd' -e \
  "CREATE USER 'repl'@'%' IDENTIFIED BY 'ReplPwd#2026'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';"

# 从库指向主库,GTID 自动定位;GET_SOURCE_PUBLIC_KEY 是为 caching_sha2 的非 TLS 连接准备的
docker exec mysql-replica mysql -uroot -p'Root_2026#pwd' -e \
  "CHANGE REPLICATION SOURCE TO SOURCE_HOST='mysql-master', SOURCE_PORT=3306, SOURCE_USER='repl', SOURCE_PASSWORD='ReplPwd#2026', SOURCE_AUTO_POSITION=1, GET_SOURCE_PUBLIC_KEY=1; START REPLICA;"

docker exec mysql-replica mysql -uroot -p'Root_2026#pwd' -e "SHOW REPLICA STATUS\G" | grep -E 'Running|Error'
# Replica_IO_Running: Yes
# Replica_SQL_Running: Yes

4.3 LOAD DATA LOCAL 与 local_infile

LOAD DATA LOCAL INFILE 的"LOCAL"指文件在客户端,这是它和容器交互最容易困惑的地方:docker exec 进容器里执行时,“客户端"是容器内的 mysql CLI,宿主机上的文件它根本看不到——要么把文件先 docker cp 进容器,要么在宿主机跑客户端直连 3306。

两层开关都得打开,缺一个报 ERROR 1148:

# 服务端:local_infile 默认 OFF
mysql -uroot -p -e "SET GLOBAL local_infile = ON;"
# 客户端:mysql CLI 也要显式开
mysql --local-infile=1 -uroot -p order_db
LOAD DATA LOCAL INFILE '/tmp/orders.csv' INTO TABLE orders
  FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

Warning:local_infile 打开后服务端会按客户端给的路径读文件,历史上有过恶意构造的"假服务端"利用 LOCAL 读取客户端文件的攻击面。生产环境不开总开关,需要时用完即关,或走服务端路径的 LOAD DATA INFILE(文件放服务器、需 secure_file_priv 允许)。


5. 首次登录与安全初始化

裸装的实例离"能上线"还差几步。这里给最小清单,备份与更完整的权限体系见 11-备份恢复与性能调优.md,权限细节在 13-常见陷阱与最佳实践.md 也有汇总。

5.1 立刻要做的三件事

-- 1) 改 root 密码(RPM 装的临时密码已强制过期,不改密这一步就是 ERROR 1820)
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Mysql#2026Root!';

-- 2) 清理匿名账号与测试库(8.0 起默认已很干净,老习惯留个检查)
SELECT user, host FROM mysql.user;
DROP DATABASE IF EXISTS test;

-- 3) 建业务账号,按库给最小权限(见 5.3)

8.0 起 root 默认认证插件是 caching_sha2_password,且只允许 localhost——远程管理用专用管理账号,别把 root 开到 %。

5.2 validate_password 复杂度组件

RPM/DEB 安装默认带 validate_password 组件,策略默认 MEDIUM:长度至少 8,要求数字、大小写、特殊字符,还会查字典文件。它会让"给 CI 建个弱密码账号"这类操作直接报错。

SHOW VARIABLES LIKE 'validate_password%';
-- validate_password.policy   MEDIUM
-- validate_password.length   8

-- 测试实例嫌烦可以卸载组件;生产不要卸,宁可降 policy 也不要裸奔
UNINSTALL COMPONENT 'file://component_validate_password';

5.3 业务账号最小权限

不要让应用连 root——一旦注入,整库陪葬。按库授权:

CREATE USER 'app_order'@'10.0.%' IDENTIFIED BY 'App#2026pwd';
GRANT SELECT, INSERT, UPDATE, DELETE ON order_db.* TO 'app_order'@'10.0.%';
-- DDL 权限平时不给,发版变更时走临时授权或专用发布账号(见 09 章 Online DDL)

GRANT 语句即时生效,不需要 FLUSH PRIVILEGES——那是手工 UPDATE 授权表时才需要的动作,很多教程把它当固定结尾是误解。

5.4 暴露面控制

  • bind-address 默认监听所有网卡;单机实例建议收紧为 127.0.0.1,云主机靠安全组挡 3306,不要靠防火墙规则注释。
  • 建议加 skip_name_resolve:授权用 IP 或 % 而不是主机名。默认开启的 DNS 反解会在连接高峰拖慢认证,且 DNS 记录漂移会让 user@host 授权悄悄失效——这是个经典隐性坑。

6. 目录与关键文件布局

以 Linux 默认 /var/lib/mysql 为例,8.4 初始化后大致长这样(Windows zip 在 datadir 同构):

/var/lib/mysql/
├── ibdata1                        # 系统表空间(8.0 起用户表默认不再落这里,剩内部对象)
├── mysql.ibd                      # 8.0 事务性数据字典本体(见 01 章)
├── #ib_16384_0.dblwr*             # 双写缓冲(8.0.20 起独立文件,防半页写坏)
├── #ib_redo1 ...                  # redo log(8.0.30+ 由 innodb_redo_log_capacity 管理)
├── undo_001 / undo_002            # undo 表空间(独立、可在线截断,服务 MVCC)
├── binlog.000001 / binlog.index   # binlog(8.0 起默认文件名前缀 binlog)
├── <库名>/<表名>.ibd               # file-per-table 表空间(默认)
└── <主机名>.err / *-slow.log       # 错误日志、慢日志(默认位置随安装方式而异)

查它们的权威方法不是背路径,而是问运行中的实例:

SELECT @@datadir, @@log_error, @@slow_query_log_file, @@general_log_file;
SHOW BINARY LOGS;
SELECT @@innodb_undo_directory, @@innodb_log_group_home_dir;

注意:错误日志在 RPM 常见 /var/log/mysqld.log、DEB 进 syslog/journald、Docker 走 stdout、Windows 在数据目录 .err——三种安装方式路径全不同,排障时先 SELECT @@log_error 或 journalctl -u mysqld,别看错地方。

每个文件"为什么存在”(双写与半页写、undo 与版本链、redo 与 binlog 的两阶段提交)是 01-核心概念与架构.md、06-MVCC.md、07-日志体系.md 的内容,这里只建立"谁在哪"的地图。


7. my.cnf 必配参数速查

原则:新实例只配下面这些,其余参数等有证据要调再动。调优方法论、刷脏水位、连接治理等深入内容在 11-备份恢复与性能调优.md,这里不展开。

[mysqld]
# --- 装完再改就是返工级参数 ---
character_set_server = utf8mb4              # 8.0 起默认即 utf8mb4,写出来图个明确
collation_server     = utf8mb4_0900_ai_ci   # 8.0 默认排序规则
default-time-zone    = '+08:00'
# lower_case_table_names = 1               # Linux 默认 0;要改必须初始化前定(见第 10 节)

# --- 内存与连接 ---
innodb_buffer_pool_size = 4G                # 专用 DB 服务器给物理内存 50%~70%,留余量给 OS
max_connections         = 500               # 应用侧配合连接池上限,别无脑拉大
open_files_limit        = 65535

# --- 持久化与复制基础 ---
innodb_redo_log_capacity = 2G               # 8.0.30+ 用这一个参数管 redo;旧的 innodb_log_file_size 系列已弃用
sync_binlog                = 1              # 与下面双 1:金融级默认
innodb_flush_log_at_trx_commit = 1

# --- 可观测性:上线就开 ---
slow_query_log  = ON
long_query_time = 1                         # 先宽后紧,配合 pt-query-digest 分析

三条务实说明:

  • innodb_dedicated_server = ON 可以一键自动化:机器专用于 MySQL 时,它让 buffer pool、redo 容量、innodb_flush_method=O_DIRECT_NOAUDIT 按物理内存自动推导,是官方给的"别抄网上模板"的出口。8.0 引入。
  • 参数改在配置文件还是在线改:动态参数用 SET PERSIST 会同时生效并写进数据目录的 mysqld-auto.cnf,优先级高于 my.cnf——排障时"my.cnf 明明改了没生效",八成是被 mysqld-auto.cnf 盖了:
SET PERSIST max_connections = 800;
SELECT * FROM performance_schema.persisted_variables;  -- 查看持久化了哪些
RESET PERSIST IF EXISTS max_connections;               -- 撤销持久化
  • 配置文件读取顺序用这条命令确认:mysqld --verbose --help 输出开头的 “Default options are read from…” 行;Windows 指定 --defaults-file 时其他位置一概不读。

8. 客户端工具与连接参数

8.1 mysql CLI 核心参数

mysql -h 127.0.0.1 -P 3306 -u app_order -p --default-character-set=utf8mb4 order_db
参数 作用 备注
-h / -P / -u / -p 主机 / 端口 / 用户 / 密码 -p 后不能加空格再写密码(-p pwd 会把 pwd 当库名);推荐只写 -p 交互输入,脚本里才 -p'密码'
--default-character-set=utf8mb4 客户端字符集 与服务器握手 SET NAMES,防乱码的第一开关
-e "SQL" 非交互执行 脚本首选,如 mysql -uroot -p -e "SHOW DATABASES"
--get-server-public-key caching_sha2 非 TLS 连接 首次认证走 RSA 公钥交换时需要(见第 10 节第 2 条)

免密做法:把账号写进 ~/.my.cnf(权限必须 600),或用 mysql_config_editor set --login-path=local ... 加密存储,脚本里 mysql --login-path=local。

8.2 交互式实用指令

-- 纵向显示:列多的表用 \G 代替 ;
SELECT * FROM mysql.user WHERE user='app_order'\G

-- 结果分页(配合 pager)
pager less -S;
SHOW FULL PROCESSLIST;
nopager;

-- 导入 SQL 文件
source /tmp/schema.sql

-- 全程记录会话输出
tee /tmp/session-20261020.log

\G、pager、tee、source 只属于交互式会话,-e 里不认(\G 除外,可写在 -e 的语句尾)。

8.3 图形工具与驱动连接串

DBeaver / Navicat / TablePlus 看个人偏好,连接参数本质相同。应用驱动要点:

Go   go-sql-driver/mysql: user:pass@tcp(10.0.0.5:3306)/order_db?charset=utf8mb4&parseTime=true&loc=Local
JDBC 8.x:  jdbc:mysql://10.0.0.5:3306/order_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
Python pymysql:  charset='utf8mb4', 并配 connect_timeout/read_timeout

乱码排查顺序背下来:客户端字符集 → 连接层(SHOW VARIABLES LIKE 'character_set_client')→ 表/列字符集 → 终端字体。九成停在第一、二层。


9. 升级与卸载注意

9.1 升级路径与方式

  • 官方支持相邻大版本升级:LTS 线走 8.0 → 8.4 → 9.7,创新线走 9.x → 26.x;5.7 存量需先 5.7 → 8.0 再到 8.4/9.7,没有跳级通道。升级目标以官方建议为准:8.4 LTS 或 9.7 LTS。
  • 升级前先跑检查:MySQL Shell 的 util.checkForServerUpgrade() 会扫出保留字冲突(如 groups、rank 成了新保留字)、弃用默认值、utf8mb3 表等。
  • 两种方式:原地升级(换二进制、启动时自动升级数据字典,快,但回滚只能靠备份)与逻辑升级(mysqldump / MySQL Shell dump & load,干净可控,见 11-备份恢复与性能调优.md)。生产更稳的做法是蓝绿:用新起 8.4 从库 + 逻辑复制/Clone plugin(8.0.17+,物理快照秒级建从,见 10-主从复制与高可用.md)切流量。
  • 不支持降级:8.x 的数据字典格式不向后兼容,回退 = 恢复备份。测试环境务必先全量备份再升。

9.2 卸载与残留清理

  • Windows:mysqld --remove MySQL84 停服务删注册;数据目录不会自动删,确认不要了再手工清。
  • Linux:apt purge mysql-community-server(只 remove 不清配置);/var/lib/mysql 永远手工确认。
  • 重装铁律:同一 datadir 换新二进制前,确认没有版本残留混用——旧 redo/数据字典配新 mysqld 轻则拒绝启动,重则把文件改坏。要么全新初始化,要么老实走升级流程。

10. 常见安装踩坑

  1. Windows 路径含中文/空格:初始化失败或服务异常,日志编码混乱。规矩:basedir/datadir 全 ASCII。

  2. 8.4 认证插件不兼容:8.4 起 mysql_native_password 默认禁用(官方方向是彻底移除)。老程序连 8.4 报 Authentication plugin 'mysql_native_password' cannot be loaded(客户端 2059)或反复 1045。正确方向是给账号换插件:

    ALTER USER 'legacy_app'@'%' IDENTIFIED WITH caching_sha2_password BY '...';

    过渡方案:启动参数 --mysql-native-password=ON(明确是临时妥协)。反向的坑同样常见:caching_sha2 账号用非 TLS 连接首次认证时走 RSA 公钥交换,客户端不带 --get-server-public-key(Go 驱动)或 allowPublicKeyRetrieval=true(JDBC)会报 “server doesn’t support…” 或认证失败——这不是密码错,是插件握手缺一步。

  3. Docker 重启数据丢失:没挂 /var/lib/mysql 卷,docker rm 即清零。容器可以随便杀,卷不可以。

  4. lower_case_table_names 初始化后不可改:Linux 默认 0(表名区分大小写),Windows 默认 1。8.0 起该参数在数据字典初始化时定死,事后硬改轻则启动失败,重则主从表名错乱。要和 Windows 行为一致,就在 mysqld --initialize 之前写进配置。

  5. 时区/字符集:SELECT NOW() 与业务差 8 小时 → 没配 default-time-zone(Docker 容器默认 UTC 尤甚);中文乱码 → 按 8.3 的四层顺序查,九成是连接串没带 utf8mb4。

  6. APT 密钥过期:apt update 报 NO_PUBKEY,处置见 3.1 注意块。

  7. my.ini 带 BOM:mysqld 解析异常,保存编码见 2.2。

  8. 服务忘了开机自启:systemctl enable;云主机重启后连不上,八成是这个。

这节只收安装期的坑,SQL/事务/索引层面的陷阱汇总在 13-常见陷阱与最佳实践.md。


实战建议

  • 起步顺序固定:装 → 立即改 root 密码并收紧 host → 建最小权限业务账号 → 开慢查询日志 → 备份链路跑通再上业务。缺任何一步,半夜出事都会找回来。
  • my.cnf 进 Git:一行改动一条记录;用了 SET PERSIST 就记住 mysqld-auto.cnf 优先级更高,排障先看它。
  • 开发机统一 Docker mysql:8.4,差异配置全部通过 conf.d 挂载对齐,不要让"我这能跑"依赖镜像默认值。
  • 连接串三件套写进团队规范:utf8mb4、超时参数、连接池上限。这三个没约定的团队,迟早用一个生产事故换回来。
  • 拿不准的当前值永远问实例:SELECT @@version, @@<参数> 比任何教程(包括本手册)都权威。