mysql - ejemplos - base de datos relacional y no relacional
Cómo almacenar una dirección compatible con IPv6 en una base de datos relacional (6)
¿Cómo puedo hacer eso?
En este momento, no se usará IPv6, pero necesito diseñar la aplicación para que esté lista para IPv6. Es necesario almacenar direcciones IP y bloques CIDR (también BGP NLRI, pero esta es otra historia) en una base de datos MySQL. Siempre he usado una INT para IPv4 + una TINYINT para masklen, pero IPv6 es de 128 bits.
¿Qué enfoque será mejor para eso? 2xBIGINT
? CHAR(16)
para almacenamiento binario CHAR(39)
para el almacenamiento de texto? 8xSMALLINT
en una mesa dedicada?
¿Qué recomendarías?
¿La dirección IP va a ser utilizada por un programa para el cual el binario tiene sentido? ¿O preferiría almacenar una representación de texto? Además, con IPv6, es menos probable que use la dirección en general y que tenga más probabilidades de usar nombres de host. Si eso es relevante depende de la aplicación, en parte. CHAR (16) sería una mala elección; char es para datos de caracteres y no le gustan las grandes transmisiones de cero bytes que prevalecen en las direcciones IPv6. 2 x BIGINT sería incómodo: dos campos que son realmente uno (además, ¿es el valor almacenado big-endian o little-endian?). Utilicé un tipo BINARIO de tamaño fijo o, si no está disponible, un tipo de blob.
Estoy trabajando con un proyecto de mayor coincidencia de prefijos, por lo que separe la dirección en 4 enteros para direcciones IPv4. Funciona bien. Extendería eso a las direcciones IPv6.
Me decantaría por el formato impreso completo estándar de 39 caracteres: -
"2001:0db8:85a3:0000:0000:8a2e:0370:7334"
40 con un terminador nulo.
Este es el formato utilizado por las herramientas de línea de comandos * nix, y el formato en el que una dirección IPV6 se informa normalmente (?).
No estoy seguro de cuál es la respuesta correcta para MySQL dado que aún no admite formatos de direcciones IPv6 de forma nativa (aunque mientras que " WL # 798: compatibilidad con MySQL IPv6 " sugiere que iba a estar en MySQL v6.0, actual la documentación no respalda eso).
Sin embargo, de los que ha propuesto, le sugiero que busque 2 * BIGINT, pero asegúrese de que NO ESTÉ FIRMADO. Hay una especie de división natural en el límite de dirección / 64 en IPv6 (ya que a / 64 es el tamaño de bloque de red más pequeño) que se alinearía muy bien con eso.
Si te estás inclinando hacia char (16), definitivamente usa binary (16). binary (n) no tiene un concepto de colación o conjunto de caracteres (o más bien, es un char (n) con un conjunto de caracteres / colación de ''binary''). El valor predeterminado para char en mysql es latin1_swedish_ci, lo que significa que intentará hacer una selección insensible a mayúsculas y minúsculas y comparaciones para valores de bytes que son puntos de código válidos en latin1, lo que le causará todo tipo de problemas inesperados.
Otra opción es usar decimal (39, 0) zerofill unsigned, no tan eficiente como dos bigints (decimal usará 4 bytes por nueve dígitos en las versiones actuales de mysql), pero le permitirá mantener todo en una columna e imprimir muy bien.
Tenga en cuenta que la longitud máxima de una dirección IPv6, incluido el identificador de ámbito, es de 46 bytes, tal como lo define INET6_ADDRSTRLEN en los encabezados C estándar. Para el uso de Internet, debe poder ignorar el identificador de zona (% 10, # eth0, etc.), pero solo tenga en cuenta que getaddrinfo devuelve un resultado más largo de lo esperado.