Frage

Ich versuche, IPv6 zu speichern Adressen in MySQL 5.0 auf effiziente Art und Weise. Ich habe die anderen Fragen im Zusammenhang mit dieser zu lesen, wie dieses . Der Autor dieser Frage entschied sich schließlich für zwei BIGINT Felder aus. Mit Hilfe ein DECIMAL (39,0) zu speichern, die IPv6-Adresse: Meine Recherchen haben auch eine anderen häufig verwendeten Mechanismus aufgedreht. Ich habe zwei Fragen darüber.

  1. Was sind die Vor- und Nachteile des DECIMAL mit (39,0) über die anderen Methoden wie 2 * BIGINT?
  2. Wie konvertiere ich (in PHP) aus dem binären Format als zurück von inet_pton () ein Dezimalstring verwendbares Format von MySQL und wie konvertiere ich zurück, so kann ich mit inet_ntop ()-recht drucken?
War es hilfreich?

Lösung 2

Hier sind die Funktionen, die ich jetzt IP-Adressen von und nach DECIMAL (39,0) Format konvertieren verwenden. Sie sind für „-Präsentation-Dezimal“ inet_ptod und inet_dtop genannt und „Dezimal-Präsentation“. Es muss IPv6 und bcmath Unterstützung in PHP.

/**
 * Convert an IP address from presentation to decimal(39,0) format suitable for storage in MySQL
 *
 * @param string $ip_address An IP address in IPv4, IPv6 or decimal notation
 * @return string The IP address in decimal notation
 */
function inet_ptod($ip_address)
{
    // IPv4 address
    if (strpos($ip_address, ':') === false && strpos($ip_address, '.') !== false) {
        $ip_address = '::' . $ip_address;
    }

    // IPv6 address
    if (strpos($ip_address, ':') !== false) {
        $network = inet_pton($ip_address);
        $parts = unpack('N*', $network);

        foreach ($parts as &$part) {
            if ($part < 0) {
                $part = bcadd((string) $part, '4294967296');
            }

            if (!is_string($part)) {
                $part = (string) $part;
            }
        }

        $decimal = $parts[4];
        $decimal = bcadd($decimal, bcmul($parts[3], '4294967296'));
        $decimal = bcadd($decimal, bcmul($parts[2], '18446744073709551616'));
        $decimal = bcadd($decimal, bcmul($parts[1], '79228162514264337593543950336'));

        return $decimal;
    }

    // Decimal address
    return $ip_address;
}

/**
 * Convert an IP address from decimal format to presentation format
 *
 * @param string $decimal An IP address in IPv4, IPv6 or decimal notation
 * @return string The IP address in presentation format
 */
function inet_dtop($decimal)
{
    // IPv4 or IPv6 format
    if (strpos($decimal, ':') !== false || strpos($decimal, '.') !== false) {
        return $decimal;
    }

    // Decimal format
    $parts = array();
    $parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0);
    $decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336'));
    $parts[2] = bcdiv($decimal, '18446744073709551616', 0);
    $decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616'));
    $parts[3] = bcdiv($decimal, '4294967296', 0);
    $decimal = bcsub($decimal, bcmul($parts[3], '4294967296'));
    $parts[4] = $decimal;

    foreach ($parts as &$part) {
        if (bccomp($part, '2147483647') == 1) {
            $part = bcsub($part, '4294967296');
        }

        $part = (int) $part;
    }

    $network = pack('N4', $parts[1], $parts[2], $parts[3], $parts[4]);
    $ip_address = inet_ntop($network);

    // Turn IPv6 to IPv4 if it's IPv4
    if (preg_match('/^::\d+.\d+.\d+.\d+$/', $ip_address)) {
        return substr($ip_address, 2);
    }

    return $ip_address;
}

Andere Tipps

Wir gingen für eine VARBINARY(16) Spalte statt und verwenden inet_pton() und inet_ntop() die Konvertierungen zu tun:

https://github.com/skion/mysql-udf-ipv6

Die Funktionen in einen laufenden MySQL-Server geladen werden können und geben Sie INET6_NTOP und INET6_PTON in SQL, ebenso wie die bekannten INET_NTOA und INET_ATON Funktionen für IPv4.

Edit: Es gibt kompatible Funktionen in MySQL jetzt, nur mit verschiedene Namen . Verwenden Sie nur die oben, wenn Sie auf Pre-5.6 MySQL sind und suchen eine günstige Zukunft Upgrade-Pfad.

DECIMAL (39)

Vorteile:

  • Arbeiten mit grundlegenden arithmetischen Operatoren (wie + und -).
  • Arbeiten mit Grunde Indizierung (exakt oder Bereich).
  • Format ist freundlich an.

Nachteile:

  • Kann außerhalb des zulässigen Bereichs Werte für IPv6 übernehmen.
  • Ist das nicht ein sehr effizienter Speichermechanismus.
  • Kann zu Verwirrung darüber, welche mathematische Operatoren oder Funktionen arbeiten und welche nicht.

BINARY (16) ...

Vorteile:

  • Die effiziente Format für die exakte Darstellung.
  • Arbeiten mit Grunde Indizierung (genauen und Bereich).
  • Werke mit Präfix Indizierung für Präfixe, die ein Vielfaches von 8 Bits sind.
  • Speichert nur gültige IPv6-Werte (obwohl nicht garantiert gültig Adressierung).
  • MySQL in späteren Versionen hat Funktionen, die Konvertierungen für dieses Format zu und von IPv6 Darstellungen unterstützen (aber nicht 4in6).

Nachteile:

  • Nicht freundlich für die Anzeige.
  • Ist das nicht freundlich mit Operatoren oder Funktionen für Zahlen gemeint.

BINARY (39) ...

Dies ist für die vollständigen Adressen (mit hexdec auch für 4in6). Kann auch eher als binären ascii sein.

Vorteile:

  • Menschen lesbar (wenn Sie können IPv6-Aufruf,).
  • Unterstützt Grund Indizierung (genaue und Bereich).
  • Unterstützung Präfix Indizierung für mehr von 4 Bit.
  • Direkt IPv6-kompatible. Keine Konvertierung notwendig.

Nachteile:

  • funktioniert nicht gut mit irgendwelchen mathematischen Funktionen oder Operatoren.
  • Die meisten ineffiziente Speicher.
  • Kann ungültige Darstellungen ermöglichen.

Skurrilitäten:

  • Ruft komplex, wenn Sie Dinge wie Groß- und Kleinschreibung wollen.
  • hat IPv6 andere Anzeigeformate obwohl für mehr Komplexität dieser Marken verwenden, wie Sie zwei Darstellungen derselben Adresse haben können, oder Sie verlieren Bereich Lookups. Kann auch am Ende zu ihm 45 Byte lang oder mit varchar / varbinary zu machen.
  • Variances dies kann die Erhaltung der Adresse unterstützen, wie sie ursprünglich empfangen. Das selten erwünscht sein kann, aber wenn es Ihnen eine Menge Vorteile verlieren.
  • Entfernen Sie die Separatoren mit Vollformat und nur Speicher ist als Hex-String für weniger Ärger und eine wenig mehr Effizienz. Sie können diese einen langen Weg nehmen, wenn Präfix Indizierung wichtig (BINARY (128)) ist.

BIGINT UNSIGNED * 2

Vorteile:

  • Arbeiten mit mathematischen Operatoren und Funktionen mit dem Vorbehalt, zusätzliche Dinge zu tun zu haben um es zwei Spalten zu sein.
  • Effiziente aber wieder mit dem Vorbehalt, dass es zwei Spalten sein wird etwas Aufwand hinzufügen.
  • Arbeiten mit grundlegenden Indizes (genau, Bereich).
  • Arbeitet mit Präfix Index, wenn Präfix 64 Bit ist.
  • Display-freundliches Format.

Nachteile:

  • Zwei Spalten macht es nicht-atomare und bedeutet eine Menge von Operationen auf sich zu verdoppeln.

Skurrilitäten:

  • Viele moderne Sprachen und Systeme geben 64 Bit ints aber nicht ohne Vorzeichen. Unterzeichnet ist problematisch. Negative Zahlen vorhanden als niedriger als positiv, aber ihre Bitfolgen sind tatsächlich höher. Aus diesem Grunde ist es stattdessen gemeinsam 4 * INT zu verwenden UNSIGNED.
  • Ähnlich Menschen könnte es für Präfix Indizierung brechen und Sie können mindestens bis 8 Bit (TINYINT UNSIGNED) gehen. Einige Leute auch den BIT machen könnte (1) Geben Sie für die vollständige Präfix Indizierung, unter der Annahme, MySQL Co postulieren Indizes auf Bittypen richtig.
  • Wieder in ähnlicher Weise mit vier Spalten einige Operationen, die Dinge verlangen wie von auf zu einem anderen tragen, sind ironischerweise leichter durch Bits während Berechnungen nachzulassen (Zwischenwerte in den Berechnungen noch können 64-Bit sein).

Zusammenfassung

Die Menschen werden verschiedene Formate aus unterschiedlichen Gründen verwenden. Nach hinten kann die Kompatibilität ein Grund sein, und das hängt davon ab, was für IPv4 getan wurde. Andere davon abhängen, wie die Adressen verwendet werden und optimisations um die. Sie können mehr als ein Ansatz sehen verwendet wird.

B16 ist ein guter Standard-Ansatz, da es die effizienteste und stressfrei ist.

Für Umrechnungen in PHP Sie können sie von Hand tun, wenn Sie erforschen:

  • gmp oder bcmath
  • PHP Nummer Handhabung und Bit-Operatoren sein, besonders bewusst Einschränkungen auf int oder sowie Funktionen schweben, die von ihnen abhängig sind, die sonst nützlich
  • erscheinen mag
  • Die IPv6-Formate
  • pack / auspacken, bin2hex / HEX2BIN.

Ich würde empfehlen, aber eine gemeinsame Bibliothek für IPv6 die verschiedenen Anzeigeformaten zu tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top