Как было запрошено в ipv6-способные функции inet_aton и inet_ntoa, необходимые", в настоящее время нет функции MySQL для хранения адресов IPv6. Каким будет рекомендуемый тип/функция данных для хранения/вставки? (Я не собираюсь хранить их как строку). Я также не хочу отделять адрес IPv6 от 2 INT.
Хранение адресов IPv6 в MySQL
Ответ 1
Как насчет:
BINARY(16)
Это должно быть достаточно эффективным.
В настоящее время нет функции для преобразования текстовых IPv6-адресов из/в двоичный файл на сервере MySQL, как указано в этом отчете об ошибке. Вам нужно либо сделать это в своем приложении, либо, возможно, сделать UDF (пользовательская функция) на сервере MySQL, чтобы это сделать.
UPDATE:
MySQL 5.6.3 имеет поддержку адресов IPv6, см. следующее: " INET6_ATON (expr)".
Тип данных VARBINARY(16) вместо BINARY(16), как я предложил ранее. Единственная причина этого в том, что функции MySQL работают как для IPv6, так и для IPv4-адресов. BINARY(16) подходит для хранения только адресов IPv6 и сохраняет один байт. VARBINARY(16) следует использовать при работе с адресами IPv6 и IPv4.
Реализация для более старых версий MySQL и MariaDB см. в следующем: " РАСШИРЕНИЕ MYSQL 5 С ФУНКЦИЯМИ IPV6.
Ответ 2
Никто не опубликовал полный рабочий ответ (и во многих примерах используется Windows ::1 который может вводить в заблуждение для реальных (или "производственных") сред) где угодно (по крайней мере, я могу найти), так что вот:
- Формат для хранения.
- Пример запроса
INSERTс использованием достаточно сложного IP-адреса IPv6. - Пример
SELECT, запрос, который вы будете иметь возможностьechoна IPv6 IP - адрес клиента. - Устранение неполадок, чтобы убедиться, что вы не пропустили ни один устаревший код.
Я изменил все имена столбцов на ipv6 чтобы отразить, что они должным образом поддерживают IPv6 (и это позволяет вам сохранить старый столбец ip без изменений). Можно сохранить столбец ip столбце ipv6 а затем просто DROP столбец ip только вы убедитесь, что преобразование сработало; когда у меня действительно будет время, я добавлю это в этот пост.
Тип данных IPv6
Как уже упоминалось, VARBINARY 16 - желательный путь, пока AMD не благословит нас 128-битными процессорами, а базы данных не будут обновлены для поддержки 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 Query
Очевидно, нам нужно сохранить IP-адрес IPv6, прежде чем мы сможем 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 Query
Код 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), это сжатая/сокращенная версия. Существует код, делающий его официальной полноформатной версией, но это экономит время для меня и других, потому что эта Q/A - та, которая продолжает появляться.
Важно: только то, что некоторые IPv6-адреса выглядят так, как будто они вписываются в bigint, не означает, что через две минуты кто-то с большим IPv6-адресом не остановится и не нанесет ущерб.
Надеемся, что это спасет некоторых людей от безумия открытия еще двух дюжин вкладок. Когда у меня будет время в будущем, я добавлю дополнительный код PHP, который расширяет сжатый IPv6 до полного формального формата.
Поиск проблемы
Если по какой-то причине сохранение и/или получение адресов IPv6 не работает, возьмите себе копию Advanced Find and Replace (работает в Wine быстрее, чем встроенный в Linux grep); используйте это преимущественно для поиска, а не замены. Убедитесь, что ваш код соответствует везде в вашем программном обеспечении.
- Все переменные
$ipдолжны быть преобразованы в$ipv6чтобы вы знали, что этот бит покрыт. - Не забудьте удалить окончание
)для следующих четырех шагов: - Искать все экземпляры PHP
inet_pton(функции и удалять их). - Найдите все экземпляры PHP
inet_ntop(функции и удалите их). - Найдите все экземпляры SQL
INET_ATON(функции и удалите их). - Найдите все экземпляры SQL
INET_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'));$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-адреса, а не потенциально испорченные версии, если вы знаете, что что-то не так до начала отладки.
Ответ 3
Отличный пример, однако я отметил следующее. Это работает, только если одна версия mysql имеет функцию INET6_ATON. В противном случае сообщение об ошибке может быть что - то вроде: что FUNCTION DOES NOT EXIST.