在MySQL中存储IPv6地址

时间:2011-08-06 01:14:02

标签: mysql sql

正如“ipv6-capable inet_aton and inet_ntoa functions needed”中所要求的那样,目前没有用于存储IPv6地址的MySQL函数。什么是用于存储/插入的推荐数据类型/功能? (我不打算将它们存储为字符串)。我也不想将IPv6地址分成2个INT。

3 个答案:

答案 0 :(得分:79)

怎么样:

BINARY(16)

这应该足够有效。

目前没有在MySQL服务器中将文本IPv6地址从/转换为二进制文件的功能,如错误报告中所述。您需要在应用程序中执行此操作,或者可能在MySQL服务器中创建UDF(用户定义函数)来执行此操作。

<强>更新

MySQL 5.6.3支持IPv6地址,请参阅以下内容:“INET6_ATON(expr)”。

我之前建议的数据类型为VARBINARY(16)而不是BINARY(16)。唯一的原因是MySQL功能适用于IPv6和IPv4地址。 BINARY(16)适用于仅存储IPv6地址并保存一个字节。处理IPv6和IPv4地址时应使用VARBINARY(16)

旧版MySQL和MariaDB的实现,请参阅以下内容:“EXTENDING MYSQL 5 WITH IPV6 FUNCTIONS”。

答案 1 :(得分:6)

没有人发布完整的工作答案(许多示例使用Windows ::1,这些 可能会误导实时(或#34;生产&#34;)环境)任何地方(至少我能找到)所以这里是:

  1. 要存储的格式。
  2. 使用相当复杂的IPv6 IP地址查询示例INSERT
  3. 示例SELECT查询您将能够echo将IPv6 IP地址返回给客户端。
  4. 排除故障以确保您没有错过任何遗留代码。
  5. 我将所有列名更改为ipv6,以反映他们正确支持IPv6(这样可以保持旧列ip完好无损)。可以在ip列中存储ipv6列,然后在您确定转换有效后再点击ip列;当我真的有时间时,我会将其添加到这篇文章中。

    IPv6数据类型

    正如已经提到的那样VARBINARY 16是一种理想的方式,直到AMD用128位CPU祝福我们并更新数据库以支持128位整数(我说得对吗?)。 IPv6是128位,而不是64位。

    CREATE TABLE `example`
    (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `ipv6` VARBINARY(16) NOT NULL,
    PRIMARY KEY (`id`)
    )
    COLLATE='utf8mb4_unicode_520_ci'
    ENGINE=InnoDB;
    

    IPv6 INSERT查询

    我们显然需要在SELECT之前存储IPv6 IP地址;这是 PHP / SQL 代码:

    $ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329');
    $query1 = "INSERT INTO example (ipv6) VALUES (INET6_ATON('$ipv6'));";
    

    IPv6 SELECT查询

    PHP / SQL 代码:

    $ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329');
    $query2 = "SELECT INET6_NTOA(ipv6) AS ipv6 FROM example WHERE ipv6=INET6_ATON('$ipv6');";
    

    这将返回fe80::202:b3ff:fe1e:8329;不,不是完整的IPv6(FE80:0000:0000:0000:0202:B3FF:FE1E:8329),它是一个浓缩/速记版本。有代码使它成为正式的完整版本,但这是为了节省自己和其他人的时间,因为这个 Q / A是一个不断出现的。

    重要提示,只是因为某些 IPv6地址看起来就像他们适合bigint一样不是意味着两分钟之后,拥有更大IPv6地址的人不会停下来并造成严重破坏。

    希望这可以使一些人免于打开另外两打标签的疯狂。当我将来有时间时,我会添加额外的PHP代码,将浓缩的IPv6扩展为完整的正式格式。

    <强>疑难解答

    如果出于某种原因存储和/或检索IPv6地址对您不起作用,那么请自己获取Advanced Find and Replace的副本(在Wine中比在本地grep中更快地运行;);使用此主要来查找,而不是替换。确保您的软件中的代码一致

    • 所有$ip变量必须转换为$ipv6,以便您知道自己已经覆盖了这一点。
    • 不要忘记在接下来的四个步骤中删除结尾)
    • 搜索 PHP inet_pton(函数的所有实例并将其删除。
    • 搜索 PHP inet_ntop(函数的所有实例并将其删除。
    • 搜索 SQL INET_ATON(函数的所有实例并将其删除。
    • 搜索 SQL INET_NTOA(函数的所有实例并将其删除。
    • 搜索$ipv6的所有实例,并确保所有IP-IN-TO-SQL实例都使用INET6_ATON('$ipv6'),并确保IP-FROM-SQL使用INET6_NTOA(ipv6) AS ipv6的所有实例。
    • 搜索$row1['ip']的所有实例,并将其替换为$row1['ipv6']
    • 确保$ipv6 =的所有实例都使用以下代码(更改了数据库对象引用):$ipv6 = (isset($_SERVER['REMOTE_ADDR']) && strlen($_SERVER['REMOTE_ADDR']) > 0) ? mysqli_real_escape_string($db,$_SERVER['REMOTE_ADDR']) : mysqli_real_escape_string($db,getenv('REMOTE_ADDR'));
    • 如果您在开始调试之前意识到出现了问题,请确保您的测试使用新近测试的IP地址而不是潜在的版本。

答案 2 :(得分:0)

一个很好的例子,但是我注意到了以下几点。 仅当某人的mysql版本具有INET6_ATON的功能时才有效。 否则,错误消息可能类似于:FUNCTION DOES NOT EXIST