35

我怎么做?

目前,不会使用 IPv6,但我需要设计应用程序以使其支持 IPv6。有必要在 MySQL 数据库中存储 IP 地址和 CIDR 块(也是 BGP NLRI,但这是另一回事)。我一直为 IPv4 使用 INT + 为 masklen 使用 TINYINT,但 IPv6 是 128 位的。

什么方法最适合呢?2xBIGINT? CHAR(16)用于二进制存储?CHAR(39)用于文本存储?8xSMALLINT在专门的桌子上?

你会推荐什么?

4

6 回答 6

21

我不确定哪个是 MySQL 的正确答案,因为它本身还不支持 IPv6 地址格式(尽管“ WL#798: MySQL IPv6 support ”表明它将在 MySQL v6.0 中,当前文档不支持这一点)。

但是,在您提出的建议中,我建议使用 2 * BIGINT,但请确保它们是未签名的。在 IPv6 中的 /64 地址边界处有一种自然分割(因为 /64 是最小的网络块大小),这将与它很好地对齐。

于 2009-01-07T15:17:20.103 回答
7

请注意,IPv6 地址的最大长度(包括范围标识符)为 46 个字节,由标准 C 标头中的 INET6_ADDRSTRLEN 定义。对于 Internet 使用,您应该能够忽略区域标识符(%10、#eth0 等),但请注意getaddrinfo返回的结果何时比预期的要长。

于 2010-02-06T04:25:01.523 回答
6

如果您倾向于 char(16),请务必改用 binary(16)。binary(n) 没有排序规则或字符集的概念(或者更确切地说,它是一个字符集/排序规则为“二进制”的 char(n))。mysql 中 char 的默认值是 latin1_swedish_ci,这意味着它将尝试对 latin1 中有效代码点的字节值进行不区分大小写的排序和比较,这将给你带来各种意想不到的问题。

另一种选择是使用十进制 (39, 0) 零填充无符号,效率不如两个 bigint(十进制在当前版本的 mysql 中每九位使用 4 个字节),但允许您将其全部保存在一列中并打印出来很好。

于 2009-01-07T15:38:21.810 回答
4

我会选择完整的 39 个字符的“标准”打印格式:-

“2001:0db8:85a3:0000:0000:8a2e:0370:7334”

40 带有一个空终止符。

这是 *nix 命令行工具使用的格式,并且,IPV6 地址的格式是 normaly(?) 报告的。

于 2009-01-07T15:53:28.127 回答
1

IP 地址是否将由二进制有意义的程序使用?还是存储文本表示会更好?此外,使用 IPv6,您一般不太可能使用地址,而更可能使用主机名。这是否相关部分取决于应用程序。CHAR(16) 将是一个糟糕的选择;char 用于字符数据,不喜欢 IPv6 地址中普遍存在的零字节大流。2 x BIGINT 会让人不舒服 - 两个字段实际上是一个字段(加上存储的值是大端还是小端?)。我使用了固定大小的 BINARY 类型,或者如果它不可用,则使用 blob 类型。

于 2009-01-07T15:22:49.920 回答
1

我正在处理一个最长前缀匹配的项目,因此我将地址分成 4 个整数用于 IPv4 地址。它运作良好。我会将其扩展到 IPv6 地址。

于 2009-10-18T05:27:45.037 回答