mysql多实例必须改端口,否则因操作系统级端口冲突(address already in use)导致启动失败;还需同步修改socket路径、pid-file、datadir、log-error等隔离项,确保物理资源不复用。

MySQL 多实例为什么必须改端口
不改端口就起不来——mysqld 启动时会尝试绑定 3306,第二个实例必然报错:Can't start server: Bind on TCP/IP port. Got error: 98: Address already in use。这不是配置问题,是操作系统级端口冲突,绕不开。
实际部署中,常见错误是只改了 port,却忘了同步改 socket 文件路径和 pid-file,导致后续用 mysqladmin 或 systemctl 管理时找不到进程或套接字。
-
port必须全局唯一(如3307、3308) -
socket路径不能复用(如/tmp/mysql3307.sock) -
pid-file也得独立(如/var/run/mysqld/mysqld3307.pid) - 如果用 systemd 管理,
Service段里的ExecStart必须指向对应实例的配置文件(如--defaults-file=/etc/my3307.cnf)
my.cnf 中怎么写多实例配置
别在一个 my.cnf 里堆多个 [mysqld] 段——MySQL 官方不支持同文件多实例启动。正确做法是:每个实例用独立配置文件(如 /etc/my3307.cnf),并在其中明确指定所有隔离项。
关键不是“加几个段”,而是“每个实例的资源路径必须物理隔离”。否则日志混写、数据目录错位、崩溃恢复时互相干扰。
- 必须设
datadir(如/var/lib/mysql3307),且目录权限属主为mysql:mysql -
log-error要独立(如/var/log/mysql/error3307.log) -
innodb_data_home_dir和innodb_log_group_home_dir如果显式配置,也得指向实例专属路径 - 避免使用
skip-networking——它会禁掉 TCP,只剩 socket,多实例间无法远程访问
启动失败时先看哪几个日志和命令
启动失败别急着重启,先确认是不是端口/路径/权限三连错。最有效的排查顺序是:
- 用
netstat -tlnp | grep :3307看端口是否真空闲(注意:有些云主机默认封了非标准端口,需检查安全组) - 手动运行
mysqld --defaults-file=/etc/my3307.cnf --verbose --help | head -20,确认配置文件被正确加载,且没语法错误 - 查
log-error指向的日志,重点找Starting MySQL后第一行报错,比如Can't create/write to file '/var/lib/mysql3307/ibdata1'就是权限问题 - 用
ps aux | grep mysqld看有没有残留进程占着 pid-file 或 socket
不同版本对多实例的支持差异
MySQL 5.7 和 8.0 在多实例上行为一致,但 8.0 默认启用 require_secure_transport 和更强的密码验证插件,如果两个实例共用一套用户表(比如都指向同一 datadir),会导致认证逻辑混乱——所以务必确保 datadir 完全分离。
Percona Server 或 MariaDB 的多实例机制类似,但要注意:MariaDB 10.6+ 引入了 systemd 原生多实例支持(通过 mysqld@instance-name),而官方 MySQL 还得靠自定义 service 文件。
- MySQL 8.0.30+ 不再允许
skip-grant-tables在多实例中混用,必须每个实例单独初始化 - 如果用
mysqld_multi工具,它只是个启动包装器,底层仍依赖各实例配置隔离,且已不推荐用于新部署 - Docker 场景下,端口映射(
-p 3307:3306)只是宿主机到容器的转发,容器内mysqld仍需监听3306,此时真正的隔离在容器网络层,而非my.cnf的port
端口数字本身没玄学,但别用 3306、3307 以外的“看着顺眼”的数——比如 8080 可能被 Web 服务占用,22 是 SSH,25 是邮件。查 /etc/services 或 ss -tuln 更稳妥。真正容易被忽略的是 socket 文件权限和 selinux 上下文(尤其在 CentOS/RHEL 上),哪怕配置全对,setenforce 1 时也可能静默拒绝访问。











