34 Stimmen

Wie speichert man IPv6-kompatible Adressen in einer relationalen Datenbank?

Wie kann ich das tun?

Im Moment wird IPv6 noch nicht verwendet, aber ich muss die Anwendung so gestalten, dass sie IPv6-fähig wird. Es ist notwendig, IP-Adressen und CIDR-Blöcke (auch BGP NLRI, aber das ist eine andere Geschichte) in einer MySQL-Datenbank zu speichern. Ich habe immer ein INT für IPv4 + ein TINYINT für masklen verwendet, aber IPv6 ist 128 Bit.

Welcher Ansatz ist dafür am besten geeignet? 2xBIGINT ? CHAR(16) für die binäre Speicherung? CHAR(39) für die Speicherung von Text? 8xSMALLINT in einer eigenen Tabelle?

Was würden Sie empfehlen?

20voto

Alnitak Punkte 324207

Ich bin mir nicht sicher, welches die rechts Antwort für MySQL, da es die IPv6-Adressformate noch nicht nativ unterstützt (obwohl die " WL#798: MySQL IPv6-Unterstützung " suggeriert, dass es in MySQL v6.0 sein sollte, die aktuelle Dokumentation bestätigt das nicht).

Wie auch immer, von den von Ihnen vorgeschlagenen, würde ich 2 * BIGINT vorschlagen, aber stellen Sie sicher, dass sie UNSIGNED sind. Es gibt eine Art natürliche Teilung an der /64-Adressgrenze in IPv6 (da ein /64 die kleinste Netzblockgröße ist), die gut damit übereinstimmen würde.

7voto

Steve-o Punkte 12493

Beachten Sie, dass die maximale Länge einer IPv6-Adresse, einschließlich der Bereichskennung, 46 Byte beträgt, wie durch INET6_ADDRSTRLEN in Standard-C-Headern definiert. Für die Verwendung im Internet sollten Sie die Zonenkennzeichen (%10, #eth0, usw.), aber achten Sie darauf, wenn getaddrinfo liefert ein längeres Ergebnis als erwartet.

6voto

ʞɔıu Punkte 44966

Wenn Sie zu char(16) tendieren, benutzen Sie stattdessen auf jeden Fall binary(16). binary(n) hat kein Konzept der Sortierung oder des Zeichensatzes (oder besser gesagt, es ist ein char(n) mit einem Zeichensatz/einer Sortierung von 'binary'). Die Voreinstellung für char in mysql ist latin1_swedish_ci, was bedeutet, dass es eine case-insensitive Sortierung und Vergleiche für Byte-Werte versucht, die gültige Code-Punkte in latin1 sind, was Ihnen alle Arten von unerwarteten Problemen bereiten wird.

Eine weitere Option ist die Verwendung von decimal (39, 0) zerofill unsigned, nicht ganz so effizient wie zwei bigints (decimal wird 4 Bytes pro neun Ziffern in aktuellen Versionen von mysql verwenden), aber ermöglicht es Ihnen, es alle in einer Spalte zu halten und schön ausdrucken.

4voto

James Anderson Punkte 26827

Ich würde mich für das volle "Standard"-Druckformat mit 39 Zeichen entscheiden:--

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

40 mit einem Nullterminator.

Dieses Format wird von den *nix-Befehlszeilen-Tools verwendet, und es ist das Format, in dem eine IPV6-Adresse normalerweise(?) gemeldet wird.

1voto

Jonathan Leffler Punkte 694013

Wird die IP-Adresse von einem Programm verwendet, für das eine binäre Darstellung sinnvoll ist? Oder wäre es besser, eine Textdarstellung zu speichern? Außerdem ist es bei IPv6 weniger wahrscheinlich, dass Sie die Adresse im Allgemeinen verwenden, sondern eher die Hostnamen. Ob das relevant ist, hängt zum Teil von der Anwendung ab. CHAR(16) wäre eine schlechte Wahl; char ist für Zeichendaten gedacht und mag keine großen Ströme von Null-Bytes, die in IPv6-Adressen häufig vorkommen. 2 x BIGINT wäre unangenehm - zwei Felder, die eigentlich eins sind (und wird der Wert Big-Endian oder Little-Endian gespeichert?). Ich würde einen BINARY-Typ mit fester Größe verwenden, oder wenn das nicht verfügbar ist, einen Blob-Typ.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X