首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 存儲 IP 地址最佳實踐:INT UNSIGNED + INET_ATON / INET_NTOA

     編輯:MySQL 綜合教學

MySQL 存儲 IP 地址最佳實踐:INT UNSIGNED + INET_ATON / INET_NTOA

直接用 VARCHAR(15) 存 IP 雖直觀,但查詢效率低、佔用空間大、無法利用數值範圍索引。MySQL 內建 INET_ATON() / INET_NTOA() 實現 IPv4 地址與無符號整數雙向轉換,推薦用 INT UNSIGNED(4 字節)存儲。

核心函數演示


-- IP → 數值
SELECT INET_ATON('255.255.255.255');  -- 4294967295 (2^32-1)
SELECT INET_ATON('192.168.1.1');      -- 3232235777
SELECT INET_ATON('10.10.10.10');      -- 168430090

-- 數值 → IP
SELECT INET_NTOA(4294967295);         -- 255.255.255.255
SELECT INET_NTOA(3232235777);         -- 192.168.1.1
SELECT INET_NTOA(168430090);          -- 10.10.10.10
SELECT INET_NTOA(0);                  -- 0.0.0.0(無 IP 時存 0)

建表範例


CREATE TABLE `access_log` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `client_ip` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'INET_ATON 存儲',
  `url` VARCHAR(255),
  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_ip_time` (`client_ip`, `created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

應用層寫入/查詢範例

寫入


-- Java
String ip = request.getRemoteAddr();
long ipLong = 0;
try {
    InetAddress addr = InetAddress.getByName(ip);
    byte[] bytes = addr.getAddress(); // IPv4 4 bytes
    for (byte b : bytes) {
        ipLong = (ipLong << 8) | (b & 0xFF);
    }
} catch (UnknownHostException e) { /* fallback 0 */ }
jdbcTemplate.update("INSERT INTO access_log(client_ip, url) VALUES (?, ?)", ipLong, url);

查詢:IP 範圍掃描


-- 查詢 192.168.1.0/24 網段訪問記錄
SELECT INET_NTOA(client_ip) AS ip, url, created_at
FROM access_log
WHERE client_ip BETWEEN INET_ATON('192.168.1.0') AND INET_ATON('192.168.1.255')
ORDER BY created_at DESC
LIMIT 100;

數值範圍查詢可直接命中 idx_ip_time 索引,極速返回。

效能對比

指標VARCHAR(15)INT UNSIGNED
存儲空間7~15 字節 + 1 字節長度前綴固定 4 字節
比較運算字串逐字符比較CPU 單指令整數比較
索引大小較大極小(1/3~1/4)
範圍查詢需 LIKE/字串比較,不可用索引BETWEEN 直接走索引
排序字典序(10.0.0.1 < 192.168.1.1 錯誤)數值序(正確網段順序)

IPv6 支援

MySQL 5.6+ 提供 INET6_ATON() / INET6_NTOA() 返回 VARBINARY(16)(128 位)。建表用 VARBINARY(16) 存儲,應用層同樣處理。若僅存 IPv4,也可用 INET6_ATON() 統一,查詢時 INET6_NTOA() 自動識別格式。

避坑指南

  1. 無符號:必須 INT UNSIGNED,否則 >127.255.255.255 會溢出為負數。
  2. 默認 0:代表 0.0.0.0(無 IP),而非 NULL,便於 COUNT/SUM 統計。
  3. 代理環境:讀取 X-Forwarded-For 首個非內網 IP,再轉換存儲。
  4. 備份/遷移:導出 CSV 時用 INET_NTOA(client_ip) 還原可讀 IP。

「INT UNSIGNED + INET_ATON/NTOA」是 MySQL 存 IPv4 的黃金標準,兼顧空間、速度、範圍查詢與排序正確性,請在所有新項目中落地。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved