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

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

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

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

Что ты посоветуешь?

Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
35
0
30 952
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

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

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

Принято окончательное решение: 2xBIGINT, если второй bigint равен NULL, то это означает IPv4.

azerole 13.01.2009 13:29

на самом деле - если бы я делал это, я бы оставил первый bigint как NULL для IPv4 или использовал бы отдельное поле. Таким образом, часть IPv4 появляется в наименее значимом слове.

Alnitak 13.01.2009 13:38

И если бы я делал это, я бы сохранил адреса IPv4 в формате адресов IPv6 V4COMPAT, то есть в диапазоне :: / 96.

james woodyatt 21.10.2009 09:14

Вы не можете просто использовать два BIGINT, вы должны использовать два BIGINT UNSIGNED. Если вы возьмете FFFF: FFFF: FFFF: FFFF: FFFF: FFFF: FFFF: FFFF, например, разделение его пополам и преобразование каждой стороны в ее целочисленное представление приведет к двум значениям 18,446,744,073,709,551,615. Это максимальное значение 64-битного целого числа без знака.

Billy Jo 29.10.2009 23:11

@james: теперь IPv4 сопоставленные адреса требовать :: ffff: / 96 range

NeDark 24.08.2011 04:21

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

Если вы сохраните его в BINARY, то никогда не будет никаких шансов выполнить побитовые операторы в самой БД, чтобы найти совпадающие адреса (то есть все те адреса, которые соответствуют определенной подсети)

Alnitak 07.01.2009 18:32

Вот почему я предложил текстовый формат, в котором вы можете выполнять сопоставление регулярных выражений (хотя я не упоминал об этом). Хранить его в любом двоичном формате будет непросто, если вы не обновите его до полного определяемого пользователем типа (поддерживает ли MySQL это?) И не предоставите соответствующие операторы.

Jonathan Leffler 08.01.2009 09:24

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

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

В проекте, над которым я сейчас работаю, мы используем десятичный (39,0) подход, и он работает хорошо, за некоторыми исключениями. Иногда вам нужно ОТНОСИТЬ значения для сравнения. т.е. WHERE ipv6 = CAST ('строка, содержащая числовой ipv6' AS decimal (39,0)). Специально для языков, которые не поддерживают 128-битные числовые типы, и привязка параметров библиотеки mysql недостаточно умна.

Diego 31.01.2014 01:03

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

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

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

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

Я бы не стал. Адреса IPv6 часто отображаются в сокращенном формате, и было бы также довольно неэффективно искать в таблице любой адрес, который находится в определенной подсети, особенно если подсеть охватывает малую границу.

Alnitak 07.01.2009 18:55

@ Джеймс Андерсон: И что еще хуже, вы не могли сравнить, лежит ли данный IPv6 в указанном диапазоне (геолокация, запрет диапазона IP-адресов).

Stefan Steiger 08.02.2012 15:26

@Quandary Это было верно с форматом IPv4 с точками. Однако для сравнения можно использовать распечатанный формат IPv6 в развернутом виде (39 символов).

Tiberiu-Ionuț Stan 09.06.2012 03:03

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

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

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