日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql如何高效存储IPv4、IPv6地址

發(fā)布時間:2024/3/13 数据库 67 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql如何高效存储IPv4、IPv6地址 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • 一、IPv4簡介 + 高效存儲
  • 二、 IPv6簡介 + 高效存儲(兼容IPv4)
  • 三、引用:

一、IPv4簡介 + 高效存儲

IPv4百度百科,簡單地來說IPv4地址是一個4字節(jié)的無符號整數(shù)。為了方便人類閱讀和分析,IPv4通常被寫作點分十進制的形式,即四個字節(jié)被分開用十進制寫出,中間用點分隔。所以如何存儲IPv4,在腦海中想到的第一個答案是用varchar也是很自然的事情。但是使用varchar要使用的字節(jié)數(shù)是3*4+3+1 = 16,其中1指的是varchar需要一個字節(jié)保存長度(varchar的長度小于等于255時,需要一個字節(jié)保存長度)。使用int是4個字節(jié),使用varcahr是16個字節(jié)。在《高性能MySQL 第三版》中,關(guān)于字段的設(shè)計原則有:在夠用的前提下,字節(jié)能省則省。所以用無符號的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 '登錄次數(shù)',`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 '數(shù)據(jù)更新日期,精確到微秒,數(shù)據(jù)庫自動維護',`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的字符串地址轉(zhuǎn)換成數(shù)值,
INET_NTOA() 將IPv4的數(shù)值轉(zhuǎn)換成字符串地址。

二、 IPv6簡介 + 高效存儲(兼容IPv4)

至此,我們高效地存儲了IPv4。但是,不幸的是IPv4地址(約43億個)已經(jīng)用完了。所以,現(xiàn)在很多網(wǎng)址使用IPv6(百度百科)。簡單地來說,IPv6是一個16字節(jié)的整數(shù)。如何高效存儲IPv6這個16字節(jié)的整數(shù)?當然,我們可以套用上面存儲IPv4的思路,使用16字節(jié)的整數(shù)存儲IPv6。可惜的是,MySQL不支持16字節(jié)的整數(shù)(最大為8字節(jié)的bigint類型),所以無法使用整數(shù)存儲IPv6。那么,這時候varchar似乎又成了首選答案,但真的應(yīng)該使用varchar嗎?不妨讓我們先看看IPv6的三種常見的表示方式。
一、冒分十六進制表示法
格式為X:X:X:X:X:X:X:X,其中每個X表示地址中的16b,以十六進制表示,例如:ABCD:EF01:2345:6789:ABCD:EF01:2345:6789這種表示法中,每個X的前導(dǎo)0是可以省略的,例如:
2001:0DB8:0000:0023:0008:0800:200C:417A→2001:DB8:0:23:8:800:200C:417A
二、0位壓縮表示法
在某些情況下,一個IPv6地址中間可能包含很長的一段0,可以把連續(xù)的一段0壓縮為“::”。但為保證地址解析的唯一性,地址中”::”只能出現(xiàn)一次,例如: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 → ::
三、內(nèi)嵌IPv4地址表示法
為了實現(xiàn)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 個字節(jié)。可IPv6本質(zhì)上一個16字節(jié)的數(shù)字,難道真的沒有其它辦法了嗎?在《高性能MySQL 第三版》中有句話“與CHAR和VARCHAR類似的類型還有BINARY和VARBINARY,它們存儲的是二進制字符串。二進制字符串和常規(guī)字符串非常相似,但是二進制字符串存儲的是字節(jié)碼而不是字符。”同時,要注意到VARBINARY(m),其中m表示字節(jié)數(shù)。這樣我們可以使用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 ;


INET6_ATON() 將IPv6的字符串地址轉(zhuǎn)換成數(shù)值(MySQL5.6+),
INET6_NTOA() 將IPv6的數(shù)值轉(zhuǎn)換成字符串地址(MySQL5.6+)。

三、引用:

  • MySQL官網(wǎng)
  • StackOverflow
  • IPv6百度百科
  • 《高性能MySQL 第三版》

總結(jié)

以上是生活随笔為你收集整理的mysql如何高效存储IPv4、IPv6地址的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。