Как сохранить IPv6-совместимый адрес в реляционной базе данных

Как это сделать?

Прямо сейчас, IPv6 не будет использоваться, но мне нужно разработать приложение, чтобы оно было готово к IPv6. Необходимо хранить IP-адреса и блоки CIDR (также BGP NLRI, но это еще одна история) в базе данных MySQL. Я всегда использовал INT для IPv4 + TINYINT для masklen, но IPv6 имеет 128 бит.

Какой подход лучше всего подходит для этого? 2xBIGINT? CHAR(16) для двоичного хранения? CHAR(39) для хранения текста? 8xSMALLINT в выделенной таблице?

Что вы порекомендовали бы?

Ответ 1

Я не уверен, какой правильный ответ для MySQL, учитывая, что он еще не поддерживает форматы адресов IPv6 изначально (хотя в то время как WL # 798: Поддержка MySQL IPv6 "предполагает, что он будет в MySQL версии 6.0, текущая документация не вернется к этому).

Однако из тех, что вы предложили, я предлагаю перейти на 2 * BIGINT, но убедитесь, что они НЕ ЗНАЮ. Там есть своего рода естественное разделение на границе адреса 64 в IPv6 (так как a/64 - наименьший размер netblock), который бы хорошо сочетался с этим.

Ответ 2

Если вы склоняетесь к char (16), определенно используйте вместо него двоичный код (16). binary (n) не имеет понятия сортировки или набора символов (вернее, это char (n) с кодировкой/сортировкой "двоичный" ). Значение по умолчанию для char в mysql - latin1_swedish_ci, что означает, что он попытается не сортировать регистр и сравнивать значения байтов, которые являются допустимыми кодовыми точками в latin1, что вызовет все непредвиденные проблемы.

Другой вариант - использовать десятичный (39, 0) zerofill unsigned, не такой эффективный, как два bigints (десятичный будет использовать 4 байта на девять цифр в текущих версиях mysql), но позволит вам сохранить все в одном колонки и распечатать красиво.

Ответ 3

Обратите внимание, что максимальная длина IPv6-адреса, включая идентификатор области видимости, составляет 46 байт, как определено INET6_ADDRSTRLEN в стандартных заголовках C. Для использования Интернета вы должны иметь возможность игнорировать идентификатор зоны (% 10, # eth0 и т.д.), Но просто помните, когда getaddrinfo возвращает более длинный результат, чем ожидалось.

Ответ 4

Я бы пошел на полный 39-значный "стандартный" печатный формат: -

"2001:0db8:85a3:0000:0000:8a2e:0370:7334"

40 с нулевым терминатором.

Это формат, используемый инструментами командной строки * nix, и формат, на который указывает IPv6-адрес, нормально (?).

Ответ 5

Будет ли IP-адрес использоваться программой, для которой имеет смысл двоичный код? Или вам лучше хранить текстовое представление? Кроме того, с IPv6, вы с меньшей вероятностью используете адрес в целом и чаще используете имена хостов. Отчасти это зависит от приложения. CHAR (16) - плохой выбор; char относится к символьным данным и не понравится большие потоки нулевых байтов, которые распространены в адресах IPv6. 2 x BIGINT будет неудобно - два поля, которые действительно одни (плюс - это значение, хранящееся big-endian или little-endian?). Я использовал тип BINARY с фиксированным размером или, если он не был доступен, тип blob.

Ответ 6

Я работаю с проектом с самым длинным сочетанием префикса, поэтому я разделяю адрес на 4 целых числа для адресов IPv4. Это работает хорошо. Я бы распространил это на адреса IPv6.