MySQL 8.0 双栈必须设 bind-address = ::,因其创建 AF_INET6 socket 并依赖内核 net.ipv6.bindv6only=0 接收 IPv4-mapped IPv6 连接;其他写法均无效或启动失败。

MySQL 8.0 默认不监听 IPv6,bind-address = 0.0.0.0 只开 IPv4;要真正双栈,必须设 bind-address = :: 并确认内核参数 net.ipv6.bindv6only = 0。
为什么 bind-address = :: 才是双栈开关
MySQL 8.0 不支持逗号分隔多个地址(如 0.0.0.0,::),也不认方括号语法([::])。写错会直接启动失败,报错类似:Unknown suffix '::' for variable 'bind_address'。只有 bind-address = :: 这一种写法能触发双栈监听逻辑——它让 mysqld 创建一个 AF_INET6 socket,并依赖内核的 IPV6_V6ONLY=0 行为来同时接收 IPv4-mapped IPv6 连接(即 ::ffff:192.168.1.100 这类地址)。
常见误操作:
- 留空或注释掉
bind-address:MySQL 8.0 默认等效于127.0.0.1,只限本地 IPv4 - 设成
0.0.0.0:纯 IPv4,netstat -tuln看不到:::3306 - 设成
::1:只监听本地 IPv6 回环,和127.0.0.1是两个独立通道
必须同步检查的三个系统级条件
光改配置文件不够,以下三项缺一不可:
-
skip-name-resolve = ON:否则客户端用 IPv6 地址连接时(如mysql -h 2001:db8::1),MySQL 会卡在反向 DNS 解析,最终报错Host '2001:db8::1' is not allowed to connect——这不是权限问题,是解析超时 - 内核参数
net.ipv6.bindv6only必须为0(Linux 默认值):运行sysctl net.ipv6.bindv6only验证;若为1,则::只收 IPv6,IPv4 连接会被拒绝 - 确保
skip-networking未启用,且启动时没加--skip-networking参数
防火墙与客户端连接的硬性要求
即使 MySQL 监听了 :::3306,外部仍连不上,大概率卡在这三处:
- 防火墙规则:
ip6tables或nftables默认丢弃新连接,需显式放行:-A INPUT -p tcp --dport 3306 -j ACCEPT - 云安全组:AWS、阿里云等平台的 IPv4 安全组规则**不自动覆盖 IPv6**,必须单独添加 IPv6 入方向规则(协议 TCP,端口 3306,源地址填
::/0或具体前缀) - 客户端连接格式:IPv6 地址必须用方括号包裹,例如:
mysql -h '[2001:db8::1]' -P 3306 -u root;老版本客户端(如 MySQL 5.6)可能不支持[::1],建议升级或改用mysql --protocol=TCP -h ::1
验证是否真通,别只信 netstat
netstat -tuln | grep :3306 显示 :::3306 只说明 socket 创建成功,不代表能连。必须实测:
- 本地 IPv6 回环:
mysql -h '::1' -P 3306 -u root - 本地 IPv4 回环(走双栈 socket):
mysql -h '127.0.0.1' -P 3306 -u root—— 若成功,说明bindv6only=0生效 - 远程 IPv6 地址:
mysql -h '[2001:db8::100]' -P 3306 -u user,且该用户授权必须是'user'@'2001:db8::100'或'user'@'2001:db8::%'(注意:MySQL 不支持 CIDR,%只能左对齐,且双冒号::在 pattern 中只能出现一次)
最易被忽略的是:IPv6 权限匹配不缓存,每次连接都查 mysql.user 表,FLUSH PRIVILEGES 必须执行,且授权语句中不能含域名(skip-name-resolve 启用后,'user'@'example.com' 无效)。


















