2011-08-06 74 views

回答

69

如何:

BINARY(16) 

這應該是足夠有效的。

正如該錯誤報告中指出的那樣,目前沒有將MySQL中的文本IPv6地址從/轉換爲二進制文件的功能。您可能需要在應用程序中執行此操作,或者可能在MySQL服務器中創建UDF(用戶定義的函數)來執行此操作。

UPDATE:

的MySQL 5.6.3具有支持IPv6地址,請參閱以下內容: 「INET6_ATON(expr)」。

正如我之前的建議,數據類型爲VARBINARY(16)而不是BINARY(16)。唯一的原因是MySQL函數可以同時用於IPv6和IPv4地址。 BINARY(16)適用於僅存儲IPv6地址並保存一個字節。處理IPv6和IPv4地址時應使用VARBINARY(16)

舊版本的MySQL和MariaDB的實現參見以下內容:「EXTENDING MYSQL 5 WITH IPV6 FUNCTIONS」。

+3

感謝您更新! – wallyk

+0

完美的時機!在我發佈問題後大約一個月左右,P – atx

2

沒有人發佈了一個完整的工作答案(和大量的實例使用Windows ::1它可以是非常誤導直播(或「生產」)的環境中)的任何地方(至少我能找到),所以在這裏是:

  1. 要存儲的格式。
  2. 示例INSERT使用合理複雜的IPv6 IP地址進行查詢。
  3. 示例SELECT查詢您將能夠將IP地址echo返回給客戶端。
  4. 疑難解答,以確保您沒有遺漏任何遺留代碼。

我改變了所有的列名ipv6,以反映他們正確支持IPv6的(和可以讓你保持舊列ip完好)。可以將ip列存儲在ipv6列中,然後只要確定轉換已經工作,只需要滴入ip列;當我真的有時間時,我會將其添加到這篇文章中。

IPv6的數據類型

正如已經提到VARBINARY 16是去,直到AMD祝福我們有128個CPU和數據庫進行更新,以支持128個整數的可取之道(我這麼說的是否正確?) 。 IPv6是128位,而不是64位。

CREATE TABLE `example` 
(
`id` INT(11) NOT NULL AUTO_INCREMENT, 
`ipv6` VARBINARY(16) NOT NULL, 
PRIMARY KEY (`id`) 
) 
COLLATE='utf8mb4_unicode_520_ci' 
ENGINE=InnoDB; 

IPv6的INSERT查詢

很明顯,我們需要存儲一個IPv6的IP地址纔可以SELECT它;這裏是PHP/SQL代碼

$ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329'); 
$query1 = "INSERT INTO example (ipv6) VALUES (INET6_ATON('$ipv6'));"; 

IPv6的SELECT查詢

PHP/SQL代碼

$ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329'); 
$query2 = "SELECT INET6_NTOA(ipv6) AS ipv6 FROM example WHERE ipv6=INET6_ATON('$ipv6');"; 

這將返回fe80::202:b3ff:fe1e:8329;不,不是完整的IPv6(即FE80:0000:0000:0000:0202:B3FF:FE1E:8329),它是一個精簡/簡寫版本。有代碼使其成爲正式的全長版本,但這是爲了節省我自己和其他人的時間,因爲這個問題是一直在提升。

重要:只是因爲一些 IPv6地址看起來像他們會適合於bigint意味着兩分鐘後,用更大的IPv6地址的人就不會停止,並造成嚴重破壞。

希望這可以節省一些人打開另外二十個標籤的精神錯亂。當我有將來的時間時,我會添加額外的PHP代碼,將濃縮的IPv6擴展到完整的正式格式。


故障排除

如果由於某些原因存儲和/或獲取IPv6地址,工作不適合你,然後抓住自己的Advanced Find and Replace複印件(在葡萄酒比Linux的原生grep工作更快);主要使用查找,而不是替換。確保您的軟件中的代碼是一致的

  • 所有$ip變量必須轉換爲$ipv6,所以你知道你已經有了位覆蓋。
  • 不要忘記刪除結束)爲下面四個步驟:
  • 搜索的PHPinet_pton(功能的所有實例並刪除它們。
  • 搜索PHPinet_ntop(的所有實例並刪除它們。
  • 搜索的所有實例SQLINET_ATON(函數並將其刪除。
  • 搜索的所有實例SQLINET_NTOA(函數並將其刪除。
  • 搜索$ipv6的所有實例,並確保所有IP-IN-TO-SQL實例使用INET6_ATON('$ipv6')以及IP-FROM-SQL使用INET6_NTOA(ipv6) AS ipv6的所有實例。
  • 搜索$row1['ip']的所有實例並將其替換爲$row1['ipv6']
  • 確保$ipv6 =的所有實例都使用以下代碼(數據庫對象引用已更改):$ipv6 = (isset($_SERVER['REMOTE_ADDR']) && strlen($_SERVER['REMOTE_ADDR']) > 0) ? mysqli_real_escape_string($db,$_SERVER['REMOTE_ADDR']) : mysqli_real_escape_string($db,getenv('REMOTE_ADDR'));
  • 確保您的測試使用新鮮測試,如果你知道有什麼不對勁你開始調試之前的IP地址可能拙劣的版本代替。