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

StackOverflow https://stackoverflow.com/questions/420680

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

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

Однако из тех, что вы предложили, я бы предложил 2 * BIGINT, но убедитесь, что они НЕ ПОДПИСАНЫ. На границе адреса / 64 в IPv6 существует своего рода естественное разделение (так как / 64 - это наименьший размер сетевого блока), которое хорошо согласуется с этим.

Другие советы

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top