Как сохранить IPv6-совместимый адрес в реляционной базе данных
Вопрос
Как мне это сделать?
Сейчас 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.