mysql的inet_aton/inet_ntoa仅支持ipv4,存在解析宽松、类型不安全、字符集乱码、ipv6不支持等问题,需配合正则校验、使用int unsigned存储、显式类型转换,并在mysql 8.0+中用inet6_aton处理ipv6。

MySQL 里用 INET_ATON 和 INET_NTOA 转 IP 和整数,能用,但有严重限制——只支持 IPv4,且对非法格式容忍过强,容易埋坑。
为什么 INET_ATON 会把 "127.0.0.1abc" 当成合法输入?
INET_ATON 实际上是“尽力解析”:它从左往右读取字符串,遇到非数字/点字符就截断。比如 INET_ATON('127.0.0.1abc') 返回 2130706433(即 127.0.0.1 的整数值),而 INET_ATON('999.999.999.999') 会返回 NULL(超出 32 位无符号范围)。
- 真正想校验 IPv4 格式,得配合正则:
ip REGEXP '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' - 插入前建议先用
INET_ATON(ip)判IS NOT NULL,再结合正则双重保险 - 注意:空字符串、
NULL、纯字母都会返回NULL,但像'1.2.3'这种缺段的会被补零为1.2.0.3
INET_NTOA 返回的字符串可能被自动截断或乱码?
INET_NTOA 返回的是 VARBINARY(4) 类型,在某些客户端或字符集设置下(如连接用 utf8mb4 但字段没显式声明字符集),可能显示为乱码或空字符串。根本原因是它返回的是二进制字节,不是文本。
- 安全写法是显式转成字符串:
CONVERT(INET_NTOA(ip_int), CHAR) - 存储整数时,务必用
INT UNSIGNED(不是INT),否则负数会出错——IPv4 最大值4294967295超出有符号INT上限 - 如果字段类型是
BIGINT,INET_NTOA仍能工作,但高位会被忽略,不报错也不警告
IPv6 怎么办?INET_ATON/INET_NTOA 完全不支持
这两个函数对 IPv6 返回 NULL,且 MySQL 原生没有等效函数。若必须存 IPv6,只能用 VARBINARY(16) 或 CHAR(39) 存原始字符串,自行实现转换逻辑(如用应用层处理,或 MySQL 8.0+ 的 INET6_ATON/INET6_NTOA)。
- MySQL 5.6 及更早版本:无原生 IPv6 支持,别硬套
INET_ATON - MySQL 8.0+ 可用
INET6_ATON,但它返回的是VARBINARY(16),不能直接和INET_ATON的结果混用 - 混合存储 IPv4/IPv6 时,不要试图用一个整数字段兼容两者——类型语义已断裂
最常被忽略的一点:INET_ATON 结果是无符号整数,但 MySQL 默认显示为有符号,所以 INET_ATON('255.255.255.255') 查出来可能显示成 -1(如果字段是 INT 而非 INT UNSIGNED)。这问题在线上查数据时极难察觉。











