mysql如何高效存储IPv4、IPv6地址 |
您所在的位置:网站首页 › ipv6地址使用多少数据位 › mysql如何高效存储IPv4、IPv6地址 |
目录
一、IPv4简介 + 高效存储二、 IPv6简介 + 高效存储(兼容IPv4)三、引用:
一、IPv4简介 + 高效存储
IPv4百度百科,简单地来说IPv4地址是一个4字节的无符号整数。为了方便人类阅读和分析,IPv4通常被写作点分十进制的形式,即四个字节被分开用十进制写出,中间用点分隔。所以如何存储IPv4,在脑海中想到的第一个答案是用varchar也是很自然的事情。但是使用varchar要使用的字节数是3*4+3+1 = 16,其中1指的是varchar需要一个字节保存长度(varchar的长度小于等于255时,需要一个字节保存长度)。使用int是4个字节,使用varcahr是16个字节。在《高性能MySQL 第三版》中,关于字段的设计原则有:在够用的前提下,字节能省则省。所以用无符号的int存储IPv4是最好的选择。 如何使用int类型存取IPv4? 登录日志表 login_log(MySQL5.6+): CREATE TABLE `login_log` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id', `user_id` bigint(20) NOT NULL COMMENT '用户id', `times` tinyint(3) unsigned NOT NULL COMMENT '登录次数', `login_time` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '登录时间,精确到微秒', `update_time` datetime(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '数据更新日期,精确到微秒,数据库自动维护', `ipv4` int(10) unsigned DEFAULT NULL COMMENT 'ipv4地址 int类型', `ipv4_string` varchar(16) DEFAULT NULL COMMENT 'ipv4地址 varchar类型', `ip` varbinary(16) DEFAULT NULL COMMENT 'ip地址,兼容ipv4和ipv6', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;插入一条记录: INSERT INTO login_log(user_id, times, ipv4, ipv4_string) VALUES(1, 1 ,INET_ATON("192.168.1.5"), "192.168.1.5");查询记录: SELECT *, INET_NTOA(ipv4) FROM login_log ; +----+---------+-------+----------------------------+----------------------------+------------+-------------+------+-----------------+ | id | user_id | times | login_time | update_time | ipv4 | ipv4_string | ip | INET_NTOA(ipv4) | +----+---------+-------+----------------------------+----------------------------+------------+-------------+------+-----------------+ | 1 | 1 | 1 | 0000-00-00 00:00:00.000000 | 0000-00-00 00:00:00.000000 | 3232235781 | 192.168.1.5 | NULL | 192.168.1.5 | +----+---------+-------+----------------------------+----------------------------+------------+-------------+------+-----------------+INET_ATON() 将IPv4的字符串地址转换成数值, INET_NTOA() 将IPv4的数值转换成字符串地址。 二、 IPv6简介 + 高效存储(兼容IPv4)至此,我们高效地存储了IPv4。但是,不幸的是IPv4地址(约43亿个)已经用完了。所以,现在很多网址使用IPv6(百度百科)。简单地来说,IPv6是一个16字节的整数。如何高效存储IPv6这个16字节的整数?当然,我们可以套用上面存储IPv4的思路,使用16字节的整数存储IPv6。可惜的是,MySQL不支持16字节的整数(最大为8字节的bigint类型),所以无法使用整数存储IPv6。那么,这时候varchar似乎又成了首选答案,但真的应该使用varchar吗?不妨让我们先看看IPv6的三种常见的表示方式。 一、冒分十六进制表示法 格式为X:X:X:X:X:X:X:X,其中每个X表示地址中的16b,以十六进制表示,例如:ABCD:EF01:2345:6789:ABCD:EF01:2345:6789这种表示法中,每个X的前导0是可以省略的,例如: 2001:0DB8:0000:0023:0008:0800:200C:417A→2001:DB8:0:23:8:800:200C:417A 二、0位压缩表示法 在某些情况下,一个IPv6地址中间可能包含很长的一段0,可以把连续的一段0压缩为“::”。但为保证地址解析的唯一性,地址中”::”只能出现一次,例如:FF01:0:0:0:0:0:0:1101 → FF01::1101,0:0:0:0:0:0:0:1 → ::1,0:0:0:0:0:0:0:0 → :: 三、内嵌IPv4地址表示法 为了实现IPv4-IPv6互通,IPv4地址会嵌入IPv6地址中,此时地址常表示为:X:X:X:X:X:X:d.d.d.d,前96b采用冒分十六进制表示,而最后32b地址则使用IPv4的点分十进制表示,例如::192.168.0.1与::FFFF:192.168.0.1就是两个典型的例子,注意在前96b中,压缩0位的方法依旧适用。 如果使用varchar类型保存IPv6的话,那么在存储以冒分十六进制表示的IPv6时,就需要39 + 1 = 40 个字节。可IPv6本质上一个16字节的数字,难道真的没有其它办法了吗?在《高性能MySQL 第三版》中有句话“与CHAR和VARCHAR类似的类型还有BINARY和VARBINARY,它们存储的是二进制字符串。二进制字符串和常规字符串非常相似,但是二进制字符串存储的是字节码而不是字符。”同时,要注意到VARBINARY(m),其中m表示字节数。这样我们可以使用VARBINARY(16)存储IPv6地址,并且兼容存储IPv4地址。 插入用三种不同方式表示IPv6地址的记录: INSERT INTO login_log(user_id, times, ip) VALUES(1, 2, inet6_aton("2001:db8:85a3:8d3:1319:8a2e:370:7348")); INSERT INTO login_log(user_id, times, ip) VALUES(1, 3, inet6_aton("fe80::3579:5807:93af:a2ce")); INSERT INTO login_log(user_id, times, ip) VALUES(1, 4, inet6_aton("::192.168.0.1"));查询记录: SELECT *, INET6_NTOA(ip) FROM login_log ;
|
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |