用 Docker 运行 MySQL 测试实例最省事干净,需显式指定 MYSQL_ROOT_PASSWORD,挂载配置文件和数据目录以避免版本差异与数据丢失,并注意初始化脚本仅在空数据目录时执行。
最省事、最干净的方式就是用 docker run 启一个官方镜像。它不污染宿主机,启动秒级,数据目录可挂载、端口可映射,适合单机开发和 CI 测试。
MYSQL_ROOT_PASSWORD variable is not set)-v ./my.cnf:/etc/mysql/conf.d/my.cnf 覆盖默认配置,避免因版本差异导致 sql_mode 或时区行为不一致/var/lib/mysql 到宿主机目录;不挂载的话,容器删掉数据就彻底丢了docker run --name mysql-test -d \ -p 3307:3306 \ -e MYSQL_ROOT_PASSWORD=test123 \ -v $(pwd)/data:/var/lib/mysql \ -v $(pwd)/my.cnf:/etc/mysql/conf.d/my.cnf \ -d mysql:8.0
Mac 用 brew install mysql、Ubuntu 用 apt install mysql-server 虽然方便,但容易和系统已有服务冲突,且默认配置常不适用于测试场景(比如 bind-address=127.0.0.1 不开远程、skip-networking 开着、或默认启用 validate_password 插件)。
netstat -tuln | grep :3306;若只显示 127.0.0.1:3306,外部容器或本机其他用户连不上SET GLOBAL validate_password.policy = LOW;,或在 my.cnf 中加 validate_password_policy=LOW
caching_sha2_password,老客户端(如某些 Python MySQLdb 驱动)连不上,可在配置中强制回退:default_authentication_plugin=mysql_native_password
别直接用 root 做应用连接用户——不是安全洁癖,而是权限过大反而掩盖问题(比如误删系统表、没意识到某条语句需要 FILE 权限)。
CREATE DATABASE test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;,MySQL 8.0 默认排序规则变了,utf8mb4_general_ci 已弃用GRANT ALL ON test_db.* TO 'testuser'@'%'; 后忘记 FLUSH PRIVILEGES;,否则权限不生效host 写成 localhost 会让应用走 socket 连接,而容器内通常没这个文件;应统一用 mysql-test(服务名)或 host.docker.internal(Mac/Win)Docker 官方镜像支持在首次启动时自动执行 /docker-entrypoint-initdb.d/ 下的 .sql 或 .sh 文件,但仅对空数据目录生效——也就是说,只要挂载了非空 /var/lib/mysql,这些脚本就完全不会运行。
docker restart,结果发现表始终没创建——因为数据目录已存在,init 脚本被跳过docker rm -v mysql-test 彻底
删容器+卷,或手动进容器执行 mysql -uroot -ptest123
CREATE USER,注意 MySQL 8.0 要求必须带 IDENTIFIED WITH mysql_native_password BY 'xxx',否则报错 Unknown authentication plugin: caching_sha2_password
测试环境的核心不是“能跑”,而是“行为可控”。端口、字符集、认证方式、初始化逻辑这四点一旦不明确,后面 debug 花的时间远超搭环境本身。