Domanda

Sto cercando di memorizzare indirizzi IPv6 in MySQL 5.0 in modo efficiente. Ho letto le altre domande relative a questo, come questo . L'autore di questa domanda alla fine ha scelto per due campi BIGINT. Le mie ricerche hanno anche alzato un altro meccanismo usato spesso: Utilizzo di un DECIMAL (39,0) per memorizzare l'indirizzo IPv6. Ho due domande al riguardo.

  1. Quali sono i vantaggi e gli svantaggi di usare DECIMAL (39,0) rispetto agli altri metodi, come 2 * BIGINT?
  2. Come faccio a convertire (in PHP) dal formato binario come restituito da inet_pton () per un formato stringa decimale utilizzabile da MySQL, e come faccio a convertire indietro in modo che posso pretty-stampa con inet_ntop ()?
È stato utile?

Soluzione 2

Ecco le funzioni che ora utilizzare per convertire gli indirizzi IP da e per formato decimale (39,0). Essi sono chiamati inet_ptod e inet_dtop per "presentazione a decimale" e "decimale a presentazione". Ha bisogno di supporto IPv6 e bcmath 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;
}

Altri suggerimenti

Siamo andati per una colonna VARBINARY(16) invece e utilizzare inet_pton() e inet_ntop() a fare le conversioni:

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

Le funzioni possono essere caricati in un server MySQL in esecuzione e vi darà INET6_NTOP e INET6_PTON in SQL, proprio come le note funzioni INET_NTOA e INET_ATON per IPv4.

Edit: Ci sono funzioni compatibili in MySQL ora, solo con href="http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_inet6-ntoa" rel="nofollow noreferrer"> nomi . Utilizzare solo il sopra, se si è in pre-5.6 di MySQL e sono alla ricerca di un futuro comodo percorso di aggiornamento.

DECIMAL (39)

Pro:

  • Funziona con operatori aritmetici di base (come + e -).
  • Opere con indicizzazione di base (esatto o intervallo).
  • Il formato è visualizzare amichevole.

Contro:

  • può accettare di valori gamma per IPv6.
  • Non è un meccanismo di archiviazione molto efficiente.
  • Può causare confusione su quale operatori matematici o funzioni funzionano e quali no.

BINARIO (16) ...

Pro:

  • formato più efficiente per la rappresentazione esatta.
  • Opere con indicizzazione di base (esatto e la gamma).
  • Opere con prefisso indicizzazione per i prefissi che sono multipli di 8 bit.
  • Negozi solo valori IPv6 validi (anche se non garantisce la validità di indirizzamento).
  • MySQL nelle versioni successive ha funzioni che supportano le conversioni per questo formato da e per rappresentazioni IPv6 (ma non 4in6).

Contro:

  • Non adatto per la visualizzazione.
  • non è amichevole con gli operatori o funzioni significato per i numeri.

BINARIO (39) ...

Questo è per gli indirizzi completi (utilizzando hexdec anche per 4in6). Può anche essere ASCII piuttosto che binario.

Pro:

  • leggibile (se si può chiamare IPv6).
  • supporta l'indicizzazione di base (esatto e la gamma).
  • Supporti indicizzazione prefisso per multiplo di 4 bit.
  • standard IPv6 Direttamente compatibile. Nessuna conversione necessaria.

Contro:

  • Non funziona bene con qualsiasi funzioni o operatori matematici.
  • storage più inefficiente.
  • può permettere rappresentazioni non validi.

Curiosità:

  • Ottiene complesso se si vuole le cose come case insensitive.
  • IPv6 ha altri formati di visualizzazione, anche se l'utilizzo di tali marche per ulteriori complessità, come si possono avere due rappresentazioni dello stesso indirizzo o si perde ricerche gamma. Può anche finire per dover renderlo 45 byte lungo o utilizzando varchar / varbinary.
  • varianze di questo può supportare preservare l'indirizzo di origine ricevuto. Che può raramente desiderare, ma quando si perde un sacco di vantaggi.
  • Rimuovere i separatori con il formato pieno e proprio negozio è come stringa esadecimale per meno fastidi e un po 'di più l'efficienza. Si può prendere questo una lunga strada se il prefisso indicizzazione è importante (BINARY (128)).

BIGINT UNSIGNED * 2

Pro:

  • Funziona con operatori matematici e funzioni con l'avvertenza di dover fare cose in più intorno ad esso essendo due colonne.
  • efficiente ma ancora una volta con l'avvertenza che essendo due colonne aggiungere un po 'sopra la testa.
  • Opere con gli indici di base (esatte, range).
  • Opere con indice prefisso durante prefisso è 64 bit.
  • Display disposizione amichevole.

Contro:

  • Due colonne rende non-atomico e significa il raddoppio di un sacco di operazioni su di esso.

Curiosità:

  • Molti linguaggi e sistemi moderni danno a 64 bit interi, ma non senza segno. Firmato è problematica. I numeri negativi presenti come inferiore positivo ma le loro sequenze di bit sono più elevati. Per questo motivo è comune, invece di utilizzare 4 * unsigned int.
  • Allo stesso modo la gente potrebbe disgregare per il prefisso l'indicizzazione e si può andare almeno fino a 8 bit (TINYINT senza segno). Alcune persone potrebbero anche fare uso della BIT (1) tipo per l'indicizzazione full prefisso, assumendo co indici postulare MySQL sui tipi di bit in modo corretto.
  • Sempre analogamente, con quattro colonne alcune operazioni che richiedono cose come portare dall'alto all'altro sono paradossalmente più facile a causa slack bit durante calcoli (valori intermedi in calcoli possono essere ancora 64 bit).

Riepilogo

La gente userà formati differenti per diversi motivi. Compatibilità può essere un motivo e che dipende da ciò che era stato fatto per IPv4. Altri dipendono da come gli indirizzi vengono utilizzati e optimisations intorno a quello. Si può visualizzare più di un approccio in uso.

B16 è un buon approccio di default dal momento che è il più efficiente e senza problemi.

Per le conversioni in PHP si può fare a mano se si ricerca:

  • GMP o bcmath
  • operatori
  • PHP movimentazione numero e bit a bit, essere particolarmente sensibile limitazioni int o float nonché funzioni che dipendono da loro che altrimenti potrebbero sembrare utile
  • I formati IPv6
  • pacchetto / decomprimere, BIN2HEX / HEX2BIN.

Suggerirei però utilizzando una libreria comune per affrontare i vari formati di visualizzazione di IPv6.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top