Como armazenar endereço compatível com IPv6 em um banco de dados relacional

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

  •  05-07-2019
  •  | 
  •  

Pergunta

Como faço isso?

No momento, o IPv6 não será usado, mas preciso projetar o aplicativo para torná-lo pronto para IPv6. É necessário armazenar endereços IP e blocos CIDR (também BGP NLRI, mas essa é outra história) em um banco de dados MySQL. Eu sempre usei um INT para IPv4 + um Tinyint para Masklen, mas o IPv6 é de 128 bits.

Que abordagem será melhor para isso? 2xBIGINT? CHAR(16) Para armazenamento binário? CHAR(39) para armazenamento de texto? 8xSMALLINT em uma tabela dedicada?

O que você recomendaria?

Foi útil?

Solução

Não tenho certeza de qual é o certo Resposta para MySQL, uma vez que ainda não suporta formatos de endereço IPv6 nativamente (embora enquanto "WL#798: Suporte MySQL IPv6"Sugere que seria no MySQL v6.0, a documentação atual não backup).

No entanto, daqueles que você propôs, eu sugeriria ir para 2 * bigint, mas certifique -se de que não sejam assinados. Existe uma espécie de divisão natural no limite de endereço /64 no IPv6 (já que A /64 é o menor tamanho de rede) que se alinharia bem com isso.

Outras dicas

Observe que o comprimento máximo de um endereço IPv6, incluindo o Scope Identifier, é de 46 bytes, conforme definido pelo INET6_ADDRSTRLEN nos cabeçalhos C Standard. Para o uso da Internet, você poderá ignorar o Identificador de zona (%10, #eth0, etc), mas esteja ciente quando getaddrinfo Retorna um resultado mais longo do que o esperado.

Se você estiver inclinado para char (16), use definitivamente o binário (16). O binário (n) não possui um conceito de agrupamento ou conjunto de caracteres (ou melhor, é um char (n) com um charset/agrupamento de 'binário'). O padrão para char no MySQL é Latin1_Swedish_Ci, o que significa que tentará classificar e comparações insensíveis a casos para valores de bytes que são pontos de código válidos no Latin1, o que causará todos os tipos de problemas inesperados.

Outra opção é usar o zerofilo decimal (39, 0) sem assinatura, não tão eficiente quanto dois bigints (Decimal usará 4 bytes por nove dígitos nas versões atuais do MySQL), mas permitirá que você mantenha tudo em uma coluna e impressão fora bem.

Eu iria para o formato impresso "padrão" de 39 caracteres de 39:-

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

40 com um terminador nulo.

Este é o formato usado pelas ferramentas de linha de comando *nix e, o formato de um endereço IPv6 é normal (?)

O endereço IP será usado por um programa para o qual o binário faz sentido? Ou você seria melhor armazenar uma representação de texto? Além disso, com o IPv6, é menos provável que você use o endereço em geral e com maior probabilidade de usar nomes de host. Se isso é relevante depende do aplicativo, em parte. Char (16) seria uma má escolha; O CHAR é para dados de caracteres e não gosta de grandes fluxos de zero bytes que prevalecem nos endereços IPv6. 2 x Bigint seria desconfortável-dois campos que são realmente um (além do valor armazenado Big-Endian ou Little-Endian?). Eu tinha usado um tipo binário de tamanho fixo, ou se isso não estiver disponível, um tipo de blob.

Estou trabalhando com um projeto de correspondência de prefixo mais longa, então separo o endereço em 4 números inteiros para endereços IPv4. Isso funciona bem. Eu estenderia isso aos endereços IPv6.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top