后续实验会修改表结构、事务、日志和复制配置,有些实验还会主动终止实例。开始之前需要准备一个与生产环境完全隔离、可以重建并且能够保存证据的 MySQL 8.4 实例。

本文只完成环境部署和基线采集,不讨论订单表设计、索引选择、事务机制或性能结论。

一、完成本文后应具备什么

  • 一个仅绑定本机地址的 MySQL 8.4 Docker 实例;
  • 一个独立网络、独立数据卷和专用实验数据库;
  • 一个权限限定在实验数据库内的普通账号;
  • 一份包含版本、镜像、会话、InnoDB、binlog、GTID 和刷盘参数的基线;
  • 一套可以区分“重启实例”和“清空数据重新初始化”的操作流程。

二、固定实验边界

本文统一使用以下名称,后续文章直接复用:

对象 固定值 用途
Docker 网络 mysql-lab-net 隔离后续 source、replica 和 restore 容器
source 容器 mysql-lab 主实验实例
source 数据卷 mysql-lab-data 持久化 MySQL 数据目录
本机地址 127.0.0.1:33060 避免向局域网暴露 MySQL 端口
实验数据库 mysql_lab 承载后续公共表和实验数据
普通账号 'lab'@'%' 执行数据库范围内的实验

文中的 rootpass 和 labpass 只用于本机可丢弃环境,不得复用到生产、测试或其他包含重要数据的实例。删除容器不会自动删除命名数据卷;删除 mysql-lab-data 才会清除实验数据。

三、部署前检查

先确认 Docker 可用,并检查同名对象是否已经存在:

docker version
docker network inspect mysql-lab-net
docker volume inspect mysql-lab-data
docker ps -a --filter name=mysql-lab

后三条命令在对象不存在时会返回错误,这是正常的检查结果。如果对象已经存在,先确认它确实属于本系列实验,不要为了重新执行命令而直接删除。

docker pull mysql:8.4
docker image inspect mysql:8.4 \
  --format 'image_id={{.Id}} repo_digests={{json .RepoDigests}}'
# 镜像标签 `8.4` 会随补丁版本更新。 要严格跟文章环境保持一致,可以选择使用 digest 拉取
docker pull mysql@sha256:b3b90af2a6552ae30c266fdb7d5dd55f3afb72404bb78d37fe8a23eb857fd3fb
mysql images版本

四、创建 MySQL 8.4 实例

仅在对应对象不存在时创建网络和数据卷:

docker network create mysql-lab-net
docker volume create mysql-lab-data

启动 source 实例:

docker run -d --name mysql-lab \
  --hostname mysql-lab \
  --network mysql-lab-net \
  -e MYSQL_ROOT_PASSWORD='rootpass' \
  -p 127.0.0.1:33060:3306 \
  -v mysql-lab-data:/var/lib/mysql \
  mysql:8.4 \
  --server-id=1 \
  --log-bin=mysql-bin \
  --binlog-format=ROW \
  --gtid-mode=ON \
  --enforce-gtid-consistency=ON \
  --performance-schema=ON \
  --performance-schema-events-statements-history-long-size=20000 \
  --innodb-flush-log-at-trx-commit=1 \
  --sync-binlog=1

这些参数建立的是后续实验的共同起点:开启 binary log、GTID 和 Performance Schema,并把 redo 与 binlog 的刷盘参数固定为强调持久性的组合。它们不是对所有生产环境的配置建议。

等待实例就绪,再进入 MySQL 客户端:

until docker exec mysql-lab \
  mysqladmin ping -uroot -prootpass --silent; do
  sleep 2
done

docker exec -it mysql-lab mysql -uroot -prootpass

五、创建实验数据库和账号

使用 root 账号执行:

CREATE DATABASE IF NOT EXISTS mysql_lab
  CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

CREATE USER IF NOT EXISTS 'lab'@'%' IDENTIFIED BY 'labpass';
GRANT ALL ON mysql_lab.* TO 'lab'@'%';

SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'mysql_lab';

SHOW GRANTS FOR 'lab'@'%';
mysql init

这里的 ALL ON mysql_lab.* 是为了覆盖后续建表、写入和结构变更实验,权限范围仍限制在独立实验库内。实例级基线、复制和恢复命令继续使用 root 账号,不给 lab 账号额外的全局权限。

验证普通账号可以连接实验库:

docker exec -it mysql-lab \
  mysql -h127.0.0.1 -ulab -plabpass mysql_lab

六、采集运行基线

uname -a
docker version
docker image inspect mysql:8.4 \
  --format 'image_id={{.Id}} repo_digests={{json .RepoDigests}}'
docker inspect mysql-lab \
  --format 'container_image={{.Image}}'
run base

在 MySQL 客户端中执行以下命令,并原样保存字段名和结果:

SELECT VERSION() AS mysql_version,
       @@version_comment AS version_comment,
       @@hostname AS hostname;

SELECT CONNECTION_ID() AS connection_id,
       @@autocommit AS autocommit,
       @@transaction_isolation AS transaction_isolation,
       @@session.time_zone AS session_time_zone,
       @@character_set_connection AS character_set_connection,
       @@collation_connection AS collation_connection;

SELECT @@default_storage_engine AS default_storage_engine,
       @@log_bin AS log_bin,
       @@binlog_format AS binlog_format,
       @@gtid_mode AS gtid_mode,
       @@enforce_gtid_consistency AS enforce_gtid_consistency,
       @@performance_schema AS performance_schema,
       @@innodb_flush_log_at_trx_commit AS innodb_flush_log_at_trx_commit,
       @@innodb_flush_log_at_timeout AS innodb_flush_log_at_timeout,
       @@sync_binlog AS sync_binlog;

SHOW ENGINES;
SHOW BINARY LOGS;
SHOW BINARY LOG STATUS\G
SHOW ENGINE INNODB STATUS\G

本次 binary log 观测结果:

mysql> SHOW BINARY LOGS;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 |       181 | No        |
| mysql-bin.000002 |   2996555 | No        |
| mysql-bin.000003 |      1026 | No        |
+------------------+-----------+-----------+
3 rows in set (0.00 sec)

mysql> SHOW BINARY LOG STATUS\G
*************************** 1. row ***************************
             File: mysql-bin.000003
         Position: 1026
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: caabd9e9-a73c-11f1-bea1-8afdb8cc75b9:1-8
1 row in set (0.00 sec)

SHOW BINARY LOGS 说明当前共有三个 binary log 文件,且这些文件未加密;SHOW BINARY LOG STATUS 说明当前写入文件及位置,并给出已执行 GTID 集合。

七、基线结果

项目 已填摘要
MySQL 补丁版本 8.4.11
会话隔离级别 REPEATABLE-READ
连接字符集 utf8mb4
默认存储引擎 InnoDB
镜像 ID/digest mysql@sha256:b3b90af2a6552ae30c266fdb7d5dd55f3afb72404bb78d37fe8a23eb857fd3fb
binary log 状态 已启用;共 3 个文件,当前文件为 mysql-bin.000003,位置为 1026
binary log 加密 现有 3 个文件的 Encrypted 均为 No
binlog 格式 binlog_format=ROW
已执行 GTID 集合 caabd9e9-a73c-11f1-bea1-8afdb8cc75b9:1-8
GTID 模式与一致性约束 gtid_mode=ON; enforce_gtid_consistency=ON
redo/binlog 刷盘参数 innodb_flush_log_at_trx_commit=1;innodb_flush_log_at_timeout=1;sync_binlog=1
Performance Schema performance_schema=ON(查询结果为 1)

八、验收与重建

环境准备完成需要同时满足:

  • mysql-lab 容器处于运行状态,端口只绑定 127.0.0.1:33060;
  • root 和 lab 账号均能按各自用途连接;
  • mysql_lab 使用预期字符集与排序规则;
  • 默认引擎为 InnoDB,binlog 为 ROW,GTID 和 Performance Schema 已开启;
  • innodb_flush_log_at_trx_commit=1、sync_binlog=1;
  • 至少存在一个 binary log 文件;
  • 已保存补丁版本、镜像 digest、关键变量和原始输出。

普通重启不会清空数据:

docker stop mysql-lab
docker start mysql-lab

需要从空数据目录重新初始化时,先确认目标名称,再删除实验容器和专用数据卷:

docker rm -f mysql-lab
docker volume rm mysql-lab-data

删除 mysql-lab-data 后,现有实验库和全部实验结果无法从该卷恢复。Docker 网络可以继续供后续 replica 和 restore 实例使用,不会随着 mysql-lab-data 数据一起删除。

九、基线适用边界

本篇已经完成首次实验环境部署与基线采集,具体版本、镜像和运行参数见“七、基线结果”。后续文章默认复用这套容器、数据卷和启动参数。

这份基线只能证明当前实验环境的版本、配置和观测入口,不代表生产环境的容量与延迟,也不能单独证明宿主机和存储设备的真实刷盘语义。

十、系列实验的证据规则

后续文章使用三类标签区分结论的证据来源:

  • DOCUMENTED:MySQL 8.4 官方文档明确说明;
  • OBSERVED:在本篇固定的实验环境中实际观察,并保存版本、参数、命令和原始输出;
  • INFERRED:根据文档或实验观察推导,并说明没有覆盖的边界。

参考资料