Mariadb 将IPv4转换为IPv6时MySQL bigint存储不一致/已签名与未签名
我有以下MySQL数据库表:Mariadb 将IPv4转换为IPv6时MySQL bigint存储不一致/已签名与未签名,mariadb,Mariadb,我有以下MySQL数据库表: CREATE TABLE `example` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `ip` BIGINT(11) NOT NULL, `ipv6` VARBINARY(16) NOT NULL PRIMARY KEY (`id`) ); 我的目标只是在新的IPv6列中将现有的IPv4 IP地址复制/转换为IPv6格式。因此,我运行了以下查询,该查询在我的所有测试用例中都运行良好: UPDATE example SET i
CREATE TABLE `example` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`ip` BIGINT(11) NOT NULL,
`ipv6` VARBINARY(16) NOT NULL
PRIMARY KEY (`id`)
);
我的目标只是在新的IPv6
列中将现有的IPv4 IP地址复制/转换为IPv6格式。因此,我运行了以下查询,该查询在我的所有测试用例中都运行良好:
UPDATE example SET ipv6 = INET6_ATON(INET_NTOA(ip));
这应该很简单吧?不处理1083条记录后,MariaDB返回以下错误:
列“ipv6”不能为空
我觉得很奇怪,所以我决定开始验证数据:
- 此表中有1279条记录
- 所有记录都包含一个
列的值,因此看起来不错。所以我向下滚动到第一条没有转换的记录。它的值为ip
,是11个数字,因此应该与40036798809
匹配,对吗INT(11)
- 但是,第二行未被处理(请记住,MySQL自然地按照主键
的升序执行id
查询),该记录的UPDATE
值是ip
,这是14个数字,在10317637058914
字段,对吗INT中是不可能的(11)
- 我看到其他一些整数明显超过了整数长度,所以我决定在HeidiSQL中按
对表进行ip
排序,然后突然
列的最高值记录是ip
。这是十个长度的数字。phpMyAdmin还显示了l然而,我已经切换到HeidiSQL,因为我发现它的GUI对于我的本地开发更为优越1202623438
- 经过一些研究,似乎
的数据类型长度与列范围无关。HeidiSQL只需更改BIGINT
顺序即可更改
列值!ip
- 继续阅读后,我的下一步是检查该列是有符号的还是无符号的。正如HeidiSQL所示,
列没有检查无符号,这意味着ip
列有符号,因此它的最大值为(添加的所有逗号仅用于可视化,实际值为纯数字)2147483647,而在ip
查询期间不会解析的值为40036798809更新
- 早期的研究表明,如果列中的数字大于允许值(不确定为什么会允许?),那么它将被视为最大允许值(我想在本例中为2147483647);这是真的吗
- 总之,
查询为什么不解析整个表更新
- 这取决于:MySQL和/或HeidiSQL在存储值方面有什么问题
- MariaDB/MySQL是否允许存储比表结构允许的大的数字
- 如果
列类型为ip
,那么在BIGINT(11)
查询期间如何处理值40036798809(同样,不带逗号)UPDATE
- 为最高有效IPv4 IP地址(255.255.255.255)存储的有效值是多少
- 我假设当我在HeidiSQL中排序时,它显示的是有效的最高值;这是最准确的猜测吗
您的号码40036798809似乎大于ipv4地址的最大可能值
255.255.255.255
,这会产生4.294.967.295
(或0xFFFFFFFF
)或最大的无符号longint。因此,它不可能是ipv4地址,因此为空,因此出现错误
也许您的一些号码不是IPV4地址
至于MySQL整数列的大小,我感觉它的字节大小有些混乱。你可以在上读这个主题。你的转换是正确的;你的数据是错误的。IPv4包含32位数字;你的
BIGINT
中存储的东西大于32位
这将定位坏行:
SELECT ip FROM example WHERE ip > INET_ATON('255.255.255.255');
您可能会发现196(1279-1083)行错误
(11)
是完全未使用和不相关的(除非您有ZEROFILL
)。我一直在努力部署正确的直接IPv6(完全没有IPv4,例如通过隧道)过去几天。我现在很好奇我是否能从这个转换到IPv6?理论上,是的,当然,如果你的所有设备都支持IPv6。我不太确定这会有多实际。如果你运行一个网站,并希望所有互联网都能访问它,当然不会。不,我说IPv6支持在连接上没有IPv4的情况下完全测试过,并不是说我会放弃IPv4支持。无论如何,我都想看看是否可以挽救较大的整数;但这似乎不起作用:更新示例集ipv6=if(INET6_-ATON(INET_-NTOA(ip))为NULL,INET6_-NTOA(ip),INET6_-ATON(INET_-NTOA(ip)))
INET6\u ATON返回的内容似乎是二进制的,而不是数字。请尝试以下操作:更新示例集ipv6=INET6\u ATON(coalesce(inet\u ntoa(ip),INET6\u ntoa(ip),0));