Armazenando endereço IP

25

Eu tenho que armazenar o endereço IP de todos os usuários registrados no banco de dados. Gostaria de saber quantos caracteres devo declarar para essa coluna?

Também devo dar suporte ao IPv6? Em caso afirmativo, qual é o tamanho máximo do endereço IP?

Cleankod
fonte

Respostas:

27

Não armazene como uma string. Use uma int unsignedcoluna e armazene / recupere com INET_ATON()e INET_NTOA()respectivamente. O AFAIK mysql não suporta INET_ * para ipv6.

EDITAR conforme comentário

O uso da função incorporada para converter IPs para / de números inteiros (e assim armazenar esses números inteiros no banco de dados) tem o efeito colateral de validar automaticamente esses IPs. Digamos que você armazene um IP como um VARCHAR (16), certifique-se de não armazenar IPs inválidos (como 999.999.999.999 como exemplo) com alguma validação personalizada. As funções INET_ * cuidam disso.

Mr Shunz
fonte
11
-1, os endereços IP têm até 128 bits e o maior número inteiro suportado pelo MySQL é de 64 bits.
Hendrik Brummermann 13/03/11
3
IPv4 é de 32 bits. 128 bits é para IPv6, que, como ele mencionou, o material INET_ * não suporta.
Richard
11
Para o endereço IPv6, use INET6_ATON () e INET6_NTOA () funções, veja o exemplo - rathishkumar.in/2017/08/how-to-store-ip-address-in-mysql.html
rathishDBA
6

Provavelmente é hora de começar a considerar o IPv6. O MySQL não possui métodos para converter endereços IPv6 em formato binário. Uma cadeia de quarenta caracteres manipula qualquer endereço IPv6 normal. Existe um formato que pode exceder 40 caracteres, eu consideraria improvável que ocorram práticas.

Você pode calcular o tamanho a partir das informações de que haverá no máximo 8 grupos de quatro caracteres com 7 caracteres separadores. O formato anormal substitui os dois últimos grupos por um endereço de formato IPv4. Sem compressão de endereço, ele substitui os últimos 9 caracteres por até 15 caracteres.

Se você estiver armazenando blocos, a indicação do tamanho do bloco poderá ter 4 caracteres em vez dos 3 caracteres necessários para o IPv4.

Você deve garantir que a formatação recebida seja consistente, mas todo o software que eu vi fornece formatos consistentes para os endereços.

BillThor
fonte
2
Eu concordo totalmente, o IPv6 está chegando e é melhor estar pronto para isso do que estar esperando por ele como Y2K: D
Jeff
Não apenas vindo, mas já aqui nos meus sistemas.
BillThor
6

Eu sugeriria a migração para o PostgreSQL e o uso dos tipos de dados INET ou CIDR .

CREATE TABLE test ( test_id serial PRIMARY KEY, address inet );
INSERT INTO test ( address ) VALUES ( '1.2.3.4'::inet );
INSERT INTO test ( address ) VALUES ( 'a:b::c:d'::inet );
SELECT * FROM test;
 test_id | address  
---------+----------
       1 | 1.2.3.4
       2 | a:b::c:d
jkj
fonte
Para obter quais IPs estão em uma rede SELECT * FROM test WHERE address << '1.2.3.0/24'::inet;
Jkj
4

Aqui está a melhor resposta feita em uma das listas de discussão do MySQL. Leia Melhor FieldType para armazenar o endereço IP ... .

Resumidamente, sugere, o que eu segundo, para usar INT (10) UNSIGNED.

  1. Ele usa menos memória (apenas 4 bytes)
  2. Melhor para classificar e pesquisar os intervalos de IP, especialmente se você procurar o país de origem dos visitantes.

Então, usando 192.168.10.50:

(192 * 2 ^ 24) + (168 * 2 ^ 16) + (10 * 2 ^ 8) + 50 = 3232238130 (resulta em 192.168.10.50)

No MySQL, você pode usar diretamente SELECT INET_ATON('192.168.10.50'); para obter 3232238130.

Ou

192 + (168 * 2 ^ 8) + (10 * 2 ^ 16) + (50 * 2 ^ 24) = 839559360 (Para trás, resulta em 50.10.168.192)

No MySQL, você pode usar diretamente SELECT INET_NTOA(3232238130); para 192.168.10.50voltar.

Olho
fonte
Impressionante, +1 para você !!! O uso de 4 bytes sem assinatura certamente supera a manipulação de strings a qualquer dia.
RolandoMySQLDBA 14/03
-1, os endereços IP têm até 128 bits e o maior número inteiro suportado pelo MySQL é de 64 bits.
Hendrik Brummermann 15/03
3
O IPv6 é de 128 bits, mas a conversa é sobre IPv4, que é de 32 bits. Não há necessidade de comentar cada comentário / resposta insistindo no seu conhecimento.
Eye
Sua resposta não menciona que ele lida apenas com o antigo protocolo da Internet, enquanto a pergunta menciona explicitamente o IPv6 no final. Dado que o último maior provedor de internet (pelo menos no meu país) oferecerá suporte ao IPv6 antes do final deste ano, é uma péssima idéia projetar uma estrutura de banco de dados que não possa lidar com isso.
Hendrik Brummermann 17/03/11
1

Você pode armazenar até 15 caracteres. Por favor, não use VARCHAR (15) porque são 16 bytes (o primeiro byte gerencia o comprimento da string e, portanto, a recuperação e o armazenamento mais lentos). Use CHAR (15) sempre em algo como um endereço IP.

RolandoMySQLDBA
fonte
O comprimento máximo de um endereço IP é de 45 caracteres.
Hendrik Brummermann 13/03/11
O CHAR não irá preenchê-lo com espaços?
Gaius
0

Desculpe, não posso comentar as respostas. Há uma pergunta sobre isso no stackoverflow. E eu concordo totalmente com a resposta selecionada: o uso do 2xBIGINT é provavelmente o melhor caminho para o ipv6 atualmente.

Eu sugiro ir para 2 * BIGINT, mas verifique se eles não estão assinados. Existe uma espécie de divisão natural no limite de endereço / 64 no IPv6 (já que um / 64 é o menor tamanho de bloco de rede) que se alinharia muito bem com isso.

Também é possível armazenar o ipv4 nesses bigints - marcando um deles como NULL ou usando o formato V4COMPAT

rvs
fonte