سؤال

أحاول تخزين عناوين IPv6 في MySQL 5.0 بطريقة فعالة. لقد قرأت الأسئلة الأخرى المتعلقة بذلك، مثل هذا واحد. وبعد اختار مؤلف هذا السؤال في نهاية المطاف لحقول Bigint. تحولت عمليات البحث الخاصة بي أيضا آلية أخرى تستخدم في كثير من الأحيان: استخدام عشري (39،0) لتخزين عنوان IPv6. لدي سؤالان حول ذلك.

  1. ما هي مزايا وعيوب استخدام عشري (39،0) عبر الأساليب الأخرى مثل 2 * bigint؟
  2. كيف يمكنني تحويل (في PHP) من التنسيق الثنائي كما عاد من قبل inet_pton () إلى تنسيق سلسلة عشري قابلة للاستخدام بواسطة MySQL، وكيف يمكنني تحويل مرة أخرى حتى أتمكن من الطباعة جميلة مع INET_NTOP ()؟
هل كانت مفيدة؟

المحلول 2

فيما يلي الوظائف التي أستخدمها الآن لتحويل عناوين IP من تنسيق وإلى رقم عشري (39،0). يتم تسمية INET_PTOD و INET_DTOP ل "العرض التقديمي إلى عشري" و "عشري إلى عرض تقديمي". يحتاج إلى دعم IPv6 و BCMATH في 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;
}

نصائح أخرى

ذهبنا ل VARBINARY(16) العمود بدلا من ذلك واستخدام inet_pton() و inet_ntop() للقيام بالتحويلات:

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

يمكن تحميل الوظائف في خادم MySQL قيد التشغيل وسوف تعطيك INET6_NTOP و INET6_PTON في SQL، تماما كما مألوف INET_NTOA و INET_ATON وظائف IPv4.

تحرير: هناك وظائف متوافقة في MySQL الآن، فقط مع مختلف أسماء. وبعد فقط استخدم ما ورد أعلاه إذا كنت في MySQL ما قبل 5.6 MySQL وتبحث عن مسار ترقية مستقبل مناسب.

عشري (39)

الايجابيات:

  • يعمل مع المشغلين الحساب الأساسي (مثل + و -).
  • يعمل مع الفهرسة الأساسية (بالضبط أو المدى).
  • التنسيق هو عرض ودية.

سلبيات:

  • يمكن أن تقبل من قيم النطاق ل IPv6.
  • ليست آلية تخزين فعالة للغاية.
  • يمكن أن يسبب الارتباك الذي يعمل عليه مشغلي الرياضيات أو الوظائف وما لا يفعلون ذلك.

ثنائي (16) ...

الايجابيات:

  • معظم التنسيق كفاءة للتمثيل الدقيق.
  • يعمل مع الفهرسة الأساسية (بالضبط والمدى).
  • يعمل مع الفهرسة البادئة للبادئات التي تعد مضاعفات 8 بت.
  • تخزن قيم IPv6 صالحة فقط (على الرغم من أنها لا تضمن عنونة صالحة).
  • يحتوي MySQL في الإصدارات اللاحقة على وظائف تدعم التحويلات لهذا التنسيق من وإلى تمثيل IPv6 (ولكن ليس 4in6).

سلبيات:

  • ليست ودية للعرض.
  • ليست ودية مع المشغلين أو الوظائف تعني الأرقام.

ثنائي (39) ...

هذا هو عناوين كاملة (باستخدام HexDec حتى ل 4in6). يمكن أن يكون أيضا ASCII بدلا من الثنائي.

الايجابيات:

  • مقروءة بشرية (إذا كنت تستطيع الاتصال IPv6 ذلك).
  • يدعم الفهرسة الأساسية (بالضبط والمدى).
  • يدعم الفهرسة البادئة لمضوع 4 بت.
  • IPv6 مباشرة متوافق. لا حاجة لتحويل.

سلبيات:

  • لا يعمل بشكل جيد مع أي وظائف رياضية أو مشغلي.
  • معظم التخزين غير فعال.
  • يمكن أن تسمح بتمثيلات غير صالحة.

الشذوذ:

  • يحصل معقدة إذا كنت تريد أشياء مثل غير حساسة للحالة.
  • يحتوي IPv6 على تنسيقات عرض أخرى على الرغم من استخدام تلك التي تصنع لمزيد من التعقيدات مثل تمثيلين لنفس العنوان أو تخسر عمليات البحث. يمكن حتى ينتهي الأمر بالحاجة إلى جعلها 45 بايت طويلة أو تستخدم varchar / varbinary.
  • يمكن أن تدعم الفروق من هذا الحفاظ على العنوان كما وردت في الأصل. هذا نادرا ما يكون مطلوبا ولكن عندما تفقد الكثير من الفوائد.
  • قم بإزالة الفواصل ذات التنسيق الكامل ومتجر Just String هي سلسلة عرافة لأقل من المتاعب وأكثر كفاءة أكثر قليلا. يمكنك أن تأخذ هذا طريقا طويلا إذا كان فهرسة البادئة مهمة (ثنائية (128)).

bigint unsigned * 2

الايجابيات:

  • يعمل مع مشغلي الرياضيات والوظائف مع تحذير الاضطرار إلى القيام بأشياء إضافية حولها أعمدة.
  • فعالة ولكن مرة أخرى مع تحذير أن كونها أعمدة ستضيف بعض النفقات العامة.
  • يعمل مع الفهارس الأساسية (بالضبط، المدى).
  • يعمل مع مؤشر البادئة عند البادئة 64 بت.
  • عرض تنسيق ودية.

سلبيات:

  • عمودين يجعلين غير ذري ويعني مضاعفة الكثير من العمليات عليه.

الشذوذ:

  • تعطي العديد من اللغات والأنظمة الحديثة 64 بت ints ولكنها ليست غير موقعة. الموقع هو مشكلة. الأرقام السلبية الحالية أقل من إيجابية ولكن تسلسلات البت هي في الواقع أعلى في الواقع. لهذا السبب، من الشائع بدلا من ذلك استخدام 4 * int غير موقعة.
  • وبالمثل، قد يقوم الأشخاص بخرقها فهرسة البادئة ويمكنك الذهاب على الأقل بقدر 8 بت (Tinyint Unsigned). قد يستفيد بعض الأشخاص أيضا من نوع بت (1) للحصول على فهرسة البادئة الكاملة، وتحمل فهارس Posit MySQL على أنواع BIT بشكل صحيح.
  • مرة أخرى بالمثل مع أربعة أعمدة بعض العمليات التي تتطلب أشياء مثل حملها من الداخل إلى آخر هي من السهل الناضجة عن السخرية بسبب البتات الركود أثناء الحسابات (القيم المتوسطة في الحسابات لا يزال لا يزال 64 بت).

ملخص

سوف يستخدم الناس تنسيقات مختلفة لأسباب مختلفة. قد يكون التوافق إلى الوراء أسبابا ويعتمد ذلك على ما يجري القيام به ل IPv4. يعتمد البعض الآخر على كيفية استخدام العناوين والتحقق من ذلك. قد ترى أكثر من نهج يستخدم.

B16 هو نهج افتراضي جيد لأنه مجاني الأكثر كفاءة ومتاعب.

للتحويلات في PHP، يمكنك القيام بها باليد إذا كنت أبحث:

  • GMP أو BCMATH.
  • يعتبر معالجة عدد PHP ومشغلي Bitwise، بشكل خاص القيود المفروضة على INT أو Float وكذلك الوظائف التي تعتمد عليها والتي قد تبدو مفيدة
  • تنسيقات IPv6.
  • حزمة / فك، BIN2HEX / HEX2BIN.

أود أن أوصي باستخدام مكتبة مشتركة للتعامل مع تنسيقات عرض IPv6 المختلفة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top