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

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

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

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

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

Ответы [ 6 ]

19 голосов
/ 07 января 2009

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

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

6 голосов
/ 06 февраля 2010

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

6 голосов
/ 07 января 2009

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

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

4 голосов
/ 07 января 2009

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

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

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

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

1 голос
/ 18 октября 2009

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

1 голос
/ 07 января 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...