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+):
插入一條記錄:
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地址的記錄:
查詢記錄:
SELECT *, INET6_NTOA(ip) FROM login_log ;
INET6_ATON() 將IPv6的字符串地址轉換成數值(MySQL5.6+),
INET6_NTOA() 將IPv6的數值轉換成字符串地址(MySQL5.6+)。
三、引用:
- MySQL官網
- StackOverflow
- IPv6百度百科
- 《高性能MySQL 第三版》
總結
以上是生活随笔為你收集整理的mysql如何高效存储IPv4、IPv6地址的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我要做-微处理器嵌入式系统设计师
- 下一篇: 2018年38种自由职业大盘点