在MySQL数据库中存储IP地址(IPv4和IPv6)

11

好的,我知道类似的问题可能已经被问了无数遍,但我对此真的很新手,非常感谢您的帮助。

基本上,我想将访客的IP地址存储在MySQL中以供以后检索和验证。我首先需要知道需要使用什么类型的字段来存储IP地址。如果可能的话,我也希望使系统兼容IPv6地址。

提前感谢。


2
你的地址主要用途是什么?你会查询它们吗?根据某些子网划分规则将它们拆分并进行查询?还是只是为了显示而存储它们? - Emil Vikström
2
试试这个:https://dev59.com/4XI-5IYBdhLWcg3wBjjk - Mark
好的,这是关于确认链接的。我想确保确认链接是从生成它的同一IP地址访问的。所以我要查询他们。 - Andy
5个回答

12

要存储IPv4地址,您可以使用INT UNSIGNED类型,而对于IPv6地址,您需要使用decimal(39,0)类型。要将IP地址存储在表中,可以使用INET_ATON函数:

INSERT INTO table (ipcol) VALUES (INET_ATON('192.168.0.10'));

使用函数INET_NTOA来检索它:

SELECT INET_NTOA(ipcol) AS ip FROM table;

在MySQL支持IPv6之前,此问题已得到解答;用户应注意MySQL现在本地支持IPv6:https://dev.mysql.com/doc/refman/5.6/en/miscellaneous-functions.html


谢谢,但我记得刚刚读到INET_ATON()不支持IPv6。即使它支持,我该如何使用PHP获取IPv6地址呢? - Andy
好的,谢谢。那么,我该如何在PHP中查找用户的IP地址? - Andy
看这里:http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html ;-) - aleroot
是的,对我来说这是显而易见的。如果不存在IPv6地址,它就无法获得IPv6地址... :-) - Andy
这在IPv6中不起作用,因为unsigned int不够大。你需要一个varbinary(16),就像inhan的答案所说的那样。 - Synchro

6

我使用VARBINARY(16)数据类型,并使用MySQL函数INET_ATON()插入IP地址(稍后使用反向函数INET_NTOA()读取)。


1
那么,VARBINARY(16)会支持IPv4和IPv6吗?我如何使用PHP查找访问者的IP地址? - Andy
1
你必须使用INET6_NTOA和INET6_ATON,但在MySQL 5.6.3版本之前不可用。 - Goran Jurić

1

MySQL中没有足够大的整数类型来存储IPv6地址。最紧凑的存储方式是使用类似于BINARY(16)的东西。如果您只需要存储和检索地址,并且不需要对它们执行逻辑操作(例如,网络掩码操作以查询哪些IP地址属于覆盖前缀),那么这就足够了。如果您需要进行逻辑或位操作,则需要更高级的方法:您需要将IPv6地址存储在两个单独的64位整数列中。


不,我不需要做任何更花哨的事情(只需在查询中检索/比较它们)。所以现在我需要知道的是如何使用PHP获取用户的IP地址? - Andy

0

您是正确的,但在MySQL 5.7中,可以将IPV6存储为十进制格式。此外,您还可以将IPv6转换为十进制或反向转换:

MySQL 5.0 IPV4

select INET_ATON('192.168.0.1') 返回整数值:3232235521

MySQL 5.7 IPV6

select cast(conv(substr(HEX(INET6_ATON('0:0:0:0:0:FFFF:C0A8:0001')), 1, 16), 16, 10) as decimal(65))*18446744073709551616 + 
       cast(conv(substr(HEX(INET6_ATON('0:0:0:0:0:FFFF:C0A8:0001')), 17, 16), 16, 10) as decimal(65)) 

返回bigint类型值:281473913978881


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接