一文詳解MySQL的IP地址如何在數(shù)據(jù)庫里存儲
一、為什么要存 IP 地址?
存儲 IP 地址是系統(tǒng)開發(fā)中的常見需求,主要用途包括:
- 安全審計與防護(hù):記錄用戶訪問 IP,識別惡意攻擊、異常登錄,建立 IP 黑/白名單實現(xiàn)訪問控制。
- 用戶分析與畫像:結(jié)合 IP 地理信息庫定位用戶大致地理位置,用于地域化內(nèi)容推薦、精準(zhǔn)廣告投放、市場分析及反欺詐。
- 網(wǎng)絡(luò)與設(shè)備管理:存儲網(wǎng)絡(luò)設(shè)備(路由器、服務(wù)器等)的 IP 地址,是設(shè)備統(tǒng)一管理、監(jiān)控和運(yùn)維的基礎(chǔ)。
- 日志分析與追蹤:在系統(tǒng)日志中存儲 IP 地址,是排查線上問題、追蹤用戶請求鏈路的必要信息。
- 合規(guī)與風(fēng)控:許多行業(yè)法規(guī)要求記錄用戶操作行為及 IP 地址,以滿足合規(guī)審計和風(fēng)險控制要求。
二、兩種存儲方式對比
IPv4 地址本質(zhì)是一個 32 位二進(jìn)制數(shù),通常以點分十進(jìn)制呈現(xiàn),如 192.168.1.1。
在數(shù)據(jù)庫中存儲 IP 地址,主要有兩種方式:
2.1 字符串存儲(VARCHAR)
直接將 IP 地址作為字符串存儲,IPv4 常用 VARCHAR(15)。
CREATE TABLE ip_records (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(15)
);
INSERT INTO ip_records (ip_address) VALUES ('192.168.1.1');
| 維度 | 說明 |
|---|---|
| ? 優(yōu)點 | 直觀易懂,直接插入、查詢和顯示,無需額外轉(zhuǎn)換 |
| ? 缺點 | 占用存儲空間較大;字符串比較性能較低;不利于范圍查詢 |
2.2 整數(shù)存儲(INT UNSIGNED)
將 IPv4 地址轉(zhuǎn)換為 32 位無符號整數(shù),使用 INT UNSIGNED 存儲。
CREATE TABLE ip_records (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address INT UNSIGNED
);
-- 插入時轉(zhuǎn)換
INSERT INTO ip_records (ip_address) VALUES (INET_ATON('192.168.1.1'));
-- 查詢時還原
SELECT INET_NTOA(ip_address) AS ip FROM ip_records;
| 維度 | 說明 |
|---|---|
| ? 優(yōu)點 | 僅占 4 字節(jié),空間??;整數(shù)比較性能高;天然支持范圍查詢(BETWEEN) |
| ? 缺點 | 需要額外轉(zhuǎn)換,不夠直觀,增加開發(fā)復(fù)雜度 |
2.3 綜合對比
| 對比維度 | VARCHAR(15) | INT UNSIGNED |
|---|---|---|
| 存儲空間 | ~15 字節(jié) | 4 字節(jié) |
| 索引效率 | 較低 | 較高 |
| 范圍查詢 | 不友好 | 天然支持 BETWEEN |
| 可讀性 | 直接可讀 | 需 INET_NTOA() 轉(zhuǎn)換 |
| 開發(fā)復(fù)雜度 | 低 | 中 |
推薦:對性能有要求、需要范圍查詢(如 IP 段匹配)的場景,優(yōu)先使用整數(shù)存儲。
三、MySQL 內(nèi)置函數(shù)
3.1 IPv4
| 函數(shù) | 方向 | 示例 |
|---|---|---|
INET_ATON() | 字符串 → 整數(shù) | INET_ATON('192.168.1.1') → 3232235777 |
INET_NTOA() | 整數(shù) → 字符串 | INET_NTOA(3232235777) → '192.168.1.1' |
3.2 IPv6
IPv6 地址為 128 位,無法用 INT UNSIGNED 存儲,需使用 VARBINARY(16)。
| 函數(shù) | 方向 | 示例 |
|---|---|---|
INET6_ATON() | 字符串 → 二進(jìn)制 | INET6_ATON('2001:db8::1') → VARBINARY(16) |
INET6_NTOA() | 二進(jìn)制 → 字符串 | INET6_NTOA(...) → '2001:db8::1' |
-- IPv6 存儲示例
CREATE TABLE ip_records_v6 (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARBINARY(16)
);
INSERT INTO ip_records_v6 (ip_address) VALUES (INET6_ATON('2001:db8::1'));
SELECT INET6_NTOA(ip_address) AS ip FROM ip_records_v6;
3.3 轉(zhuǎn)換原理
IPv4
IPv4 是 32 位二進(jìn)制數(shù),分為 4 個字節(jié)(Octet),每個字節(jié)對應(yīng)點分十進(jìn)制中的一段。
計算方式:每段 × 256 的冪次,然后求和(等價于將 4 個字節(jié)拼成一個 32 位無符號整數(shù))。
192.168.1.1
192 × 2563 = 192 × 16,777,216 = 3,221,225,472
168 × 2562 = 168 × 65,536 = 11,010,048
1 × 2561 = 1 × 256 = 256
1 × 256? = 1 × 1 = 1
───────────────────────────────────────────────
總和 = 3,232,235,777
從二進(jìn)制視角看更直觀:
192 → 11000000 168 → 10101000 1 → 00000001 1 → 00000001 拼接為 32 位:11000000 10101000 00000001 00000001 轉(zhuǎn)為十進(jìn)制:3,232,235,777
公式:INET_ATON(A.B.C.D) = A × 2²? + B × 2¹? + C × 2? + D
反向轉(zhuǎn)換 INET_NTOA() 就是將整數(shù)按每 8 位拆開,轉(zhuǎn)回點分十進(jìn)制。
IPv6
IPv6 是 128 位,分為 8 組,每組 16 位(2 字節(jié)),用冒號分隔的十六進(jìn)制表示。
:: 是 零壓縮(zero compression),表示中間全是 0。先展開:
2001:db8::1
↓ 展開 ::
2001:0db8:0000:0000:0000:0000:0000:0001
每組是 16 位(2 字節(jié)),8 組 × 2 字節(jié) = 16 字節(jié),所以用 VARBINARY(16) 存儲:
組1: 2001 → 0x20 0x01 組2: 0db8 → 0x0d 0xb8 組3: 0000 → 0x00 0x00 組4: 0000 → 0x00 0x00 組5: 0000 → 0x00 0x00 組6: 0000 → 0x00 0x00 組7: 0000 → 0x00 0x00 組8: 0001 → 0x00 0x01 ─────────────────────── 最終 16 字節(jié)(十六進(jìn)制): 0x20 0x01 0x0D 0xB8 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
要點:IPv6 沒有"轉(zhuǎn)成一個巨大整數(shù)"的做法,因為 128 位超出了 MySQL 整型的最大范圍(BIGINT UNSIGNED 也只有 64 位)。所以直接用原始二進(jìn)制 VARBINARY(16) 存儲,不做數(shù)值運(yùn)算,只做字節(jié)序列比較。
四、實戰(zhàn):IP 范圍查詢
整數(shù)存儲的一大優(yōu)勢是范圍查詢非常高效:
-- 查詢 192.168.1.0 ~ 192.168.1.255 網(wǎng)段內(nèi)的所有 IP
SELECT INET_NTOA(ip_address) AS ip
FROM ip_records
WHERE ip_address BETWEEN INET_ATON('192.168.1.0')
AND INET_ATON('192.168.1.255');
如果使用 VARCHAR 存儲,這種范圍查詢幾乎無法高效實現(xiàn)。
五、小結(jié)
- 能存整數(shù)就別存字符串:
INT UNSIGNED(4 字節(jié))遠(yuǎn)優(yōu)于VARCHAR(15)(15 字節(jié)),且查詢性能更好。 - IPv4 用
INET_ATON/INET_NTOA做轉(zhuǎn)換,簡單可靠。 - IPv6 用
VARBINARY(16)+INET6_ATON/INET6_NTOA,注意 IPv6 是 128 位,不能用整數(shù)類型。 - 范圍查詢場景(IP 段匹配、IP 庫查詢等)務(wù)必使用整數(shù)/二進(jìn)制存儲。
到此這篇關(guān)于一文詳解MySQL的IP地址如何在數(shù)據(jù)庫里存儲的文章就介紹到這了,更多相關(guān)MySQL IP地址在數(shù)據(jù)庫里存儲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
master and slave have equal MySQL server UUIDs 解決方法
使用rsync配置了大量mysql,省去了大量編譯和配置的時間,隨逐個修改master和slave服務(wù)器的my.cnf,后,發(fā)現(xiàn)數(shù)據(jù)不能同步2013-07-07
mysql 存儲過程判斷重復(fù)的不插入數(shù)據(jù)
這篇文章主要介紹了下面是一個較常見的場景,判斷表中某列是否存在某值,如果存在執(zhí)行某操作,需要的朋友可以參考下2017-01-01
MySQL數(shù)據(jù)庫之用戶管理與權(quán)限控制的完整指南
MySQL用戶權(quán)限管理是保障數(shù)據(jù)庫安全的關(guān)鍵環(huán)節(jié),本文詳細(xì)介紹了MySQL用戶管理的核心操作,包括用戶的創(chuàng)建,刪除,密碼修改等,幫你快速掌握安全合規(guī)的用戶權(quán)限管理方法2026-05-05
mysql數(shù)據(jù)庫的五種安裝方式總結(jié)
這篇文章主要介紹了五種在不同操作系統(tǒng)上安裝和配置MySQL的方法,包括Windows版本安裝、yum倉庫安裝、二進(jìn)制本地安裝、容器平臺安裝以及源碼部署,每種方法都介紹的非常詳細(xì),需要的朋友可以參考下2025-03-03
mysql從一張表查詢批量數(shù)據(jù)并插入到另一表中的完整實例
這篇文章主要給大家介紹了關(guān)于mysql從一張表查詢批量數(shù)據(jù)并插入到另一表中的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
使用Rotate Master實現(xiàn)MySQL 多主復(fù)制的實現(xiàn)方法
眾所周知,MySQL只支持一對多的主從復(fù)制,而不支持多主(multi-master)復(fù)制2012-05-05
以數(shù)據(jù)庫字段分組顯示數(shù)據(jù)的sql語句(詳細(xì)介紹)
本篇文章是對以數(shù)據(jù)庫字段分組顯示數(shù)據(jù)的sql語句進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06

