MySQL

2009-07-13 23 views
16

में स्टोरेज के लिए आईपीवी 6 बाइनरी से कनवर्ट करने के लिए कैसे मैं एक कुशल तरीके से MySQL 5.0 में आईपीवी 6 पते स्टोर करने की कोशिश कर रहा हूं। मैंने such as this one से संबंधित अन्य प्रश्न पढ़े हैं। उस प्रश्न के लेखक ने अंततः दो बिगिनट क्षेत्रों के लिए चुना। मेरी खोजों ने एक और अक्सर उपयोग की गई तंत्र को भी चालू कर दिया है: आईपीवी 6 पता स्टोर करने के लिए एक डेसिमल (3 9, 0) का उपयोग करना। मेरे पास इसके बारे में दो प्रश्न हैं।MySQL

  1. 2 * बिगिनट जैसी अन्य विधियों पर डेसिमल (3 9 0) का उपयोग करने के फायदे और नुकसान क्या हैं?
  2. मैं inet_pton() द्वारा MySQL द्वारा उपयोग किए जाने वाले दशमलव स्ट्रिंग प्रारूप में वापस लौटने के रूप में बाइनरी प्रारूप से (PHP में) कैसे परिवर्तित करूं, और मैं वापस कैसे परिवर्तित करूं ताकि मैं inet_ntop() के साथ सुंदर प्रिंट कर सकूं?
+0

VARCHAR फ़ील्ड का उपयोग करने में समस्या क्या है? – shadowhand

+1

एक के लिए आसान आईपी रेंज मिलान। –

उत्तर

19

यहां ऐसे फ़ंक्शंस हैं जिन्हें मैं अब आईपी पते को और डेसीमल (3 9 0) प्रारूप में परिवर्तित करने के लिए उपयोग करता हूं। उन्हें "प्रस्तुति-से-दशमलव" और "दशमलव-से-प्रस्तुति" के लिए inet_ptod और inet_dtop नाम दिया गया है। इसे PHP में आईपीवी 6 और बीसीएमएथ समर्थन की आवश्यकता है।

/** 
* 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; 
} 
+21

लड़का। अच्छी बात यह है कि उस कोड में कोई मनमाना जादू संख्या नहीं है। –

+5

यदि आप 2 की शक्तियों को जानते हैं तो वे मनमानी या जादू नहीं हैं ;-) –

+1

+1 मैं उन कार्यों को पोस्ट करने के लिए आपको 500 बार वोट देना चाहता हूं! धन्यवाद। –

30

हम बजाय एक VARBINARY(16) स्तंभ के लिए चला गया और inet_pton() और inet_ntop() का उपयोग रूपांतरण करने के लिए:

https://bitbucket.org/skion/mysql-udf-ipv6

कार्यों एक चल MySQL सर्वर में लोड किया जा सकता है और आप INET6_NTOP और INET6_PTON दे देंगे एसक्यूएल में, आईपीवी 4 के लिए परिचित INET_NTOA और INET_ATON फ़ंक्शन के रूप में।

संपादित करें: अब MySQL में संगत फ़ंक्शन हैं, बस differentnames के साथ। केवल उपर्युक्त का उपयोग करें यदि आप पूर्व-5.6 MySQL पर हैं और सुविधाजनक भविष्य अपग्रेड पथ की तलाश में हैं।

+0

अच्छा। मानक साझा होस्टिंग पर उपयोग करने योग्य नहीं है, लेकिन निश्चित रूप से एक विकल्प यदि आप अपना स्वयं का सर्वर चलाते हैं। –

+0

मैं इस दृष्टिकोण के लिए भी झुकाऊंगा। जाहिर है, यह कई साझा होस्टिंग वातावरण में काम नहीं करता है, लेकिन इस तरह के पते को संग्रहीत करने से मूल PHP की तुलना में अधिक कुशल मिलान (उदाहरण के लिए, नेटमास्क पर आधारित) की अनुमति मिलती है। –

+0

बस ध्यान दें कि ऊपर मॉड्यूल वेनिला MySQL v5.6.3 में नई आईपीवी 6 कार्यों के साथ संगत किया गया है चाहता था: INET6_ATON() और INET6_NTOA()। इस प्रकार आप उपरोक्त मॉड्यूल का उपयोग अपने पूर्व-5.6 इंस्टॉल के लिए कर सकते हैं, और पोस्ट-5.6 पर इसे एक बार अनलोड कर सकते हैं; अपने प्रश्नों को बदलने के बिना। –

0

दशमलव (39)

सकारात्मक:

बुनियादी अंकगणितीय ऑपरेटर के साथ
  • काम करता है (जैसे + और -)।
  • मूल अनुक्रमण (सटीक या सीमा) के साथ काम करता है।
  • प्रारूप अनुकूल है।

विपक्ष:

  • IPv6 के लिए सीमा मूल्यों के साथ स्वीकार कर सकते हैं।
  • एक बहुत ही कुशल भंडारण तंत्र नहीं है।
  • भ्रम पैदा कर सकता है कि कौन से गणितीय ऑपरेटरों या कार्य काम करते हैं और जो नहीं करते हैं।

द्विआधारी (16) ...

सकारात्मक:

  • सटीक प्रतिनिधित्व के लिए सबसे कुशल प्रारूप।
  • मूल अनुक्रमण (सटीक और सीमा) के साथ काम करता है।
  • उपसर्गों के लिए उपसर्ग अनुक्रमण के साथ काम करता है जो 8 बिट्स के गुणक हैं।
  • केवल वैध आईपीवी 6 मान स्टोर करता है (हालांकि वैध पते की गारंटी नहीं देता है)।
  • बाद के संस्करणों में MySQL में ऐसे फ़ंक्शन हैं जो इस प्रारूप के लिए IPv6 प्रस्तुतियों (लेकिन 4in6 नहीं) के रूपांतरणों का समर्थन करते हैं।

विपक्ष:

  • प्रदर्शन के लिए अनुकूल नहीं है।
  • संख्याओं के लिए ऑपरेटरों या कार्यों के अनुकूल नहीं है।

द्विआधारी (39) ...

यह पूर्ण पते के लिए है (यहां तक ​​कि hexdec का उपयोग कर 4in6 के लिए)। द्विआधारी के बजाय ascii भी हो सकता है।

सकारात्मक:

  • मानव पठनीय (यदि आप IPv6 कि कॉल कर सकते हैं)।
  • मूल अनुक्रमणिका (सटीक और सीमा) का समर्थन करता है।
  • 4 बिट्स के एकाधिक के लिए उपसर्ग अनुक्रमण का समर्थन करता है।
  • सीधे आईपीवी 6 संगत। कोई रूपांतरण की आवश्यकता नहीं है।

विपक्ष:

  • किसी भी गणितीय कार्य या ऑपरेटरों के साथ अच्छी तरह से काम नहीं करता।
  • सबसे अक्षम भंडारण।
  • अमान्य प्रतिनिधित्व की अनुमति दे सकता है।

ऑडिटीज:

  • इस तरह के मामले असंवेदनशील के रूप में अगर आप चीजों को चाहते जटिल हो जाता है।
  • आईपीवी 6 में अन्य डिस्प्ले प्रारूप हैं, हालांकि उनको अधिक जटिलताओं के लिए उपयोग किया जाता है जैसे कि आपके पास एक ही पते के दो प्रस्तुतियां हो सकती हैं या आप रेंज लुकअप खो देते हैं। इसे 45 बाइट लंबा या वर्कर/varbinary का उपयोग करने के अंत तक भी समाप्त हो सकता है।
  • इसका भिन्नता मूल रूप से प्राप्त पते को संरक्षित करने में सहायता कर सकता है। शायद ही कभी वांछित हो सकता है लेकिन जब आप बहुत सारे लाभ खो देते हैं।
  • विभाजक को पूर्ण प्रारूप के साथ हटाएं और केवल स्टोर कम परेशानी और थोड़ी अधिक दक्षता के लिए हेक्स स्ट्रिंग के रूप में है। यदि उपसर्ग अनुक्रमण महत्वपूर्ण है (BINARY (128)) यदि आप इसे लंबा सफर तय कर सकते हैं।

BIGINT अहस्ताक्षरित * 2

सकारात्मक:

गणितीय ऑपरेटरों और चारों ओर यह दो कॉलम की जा रही अतिरिक्त काम करने के लिए होने की चेतावनी के साथ कार्यों के साथ
  • काम करता है।
  • कुशल लेकिन फिर चेतावनी के साथ कि यह दो कॉलम होने पर कुछ ओवरहेड जोड़ देगा।
  • मूल अनुक्रमणिका (सटीक, सीमा) के साथ काम करता है।
  • प्रीफिक्स 64 बिट्स होने पर उपसर्ग अनुक्रमणिका के साथ काम करता है।
  • दोस्ताना प्रारूप प्रदर्शित करें।

विपक्ष:

  • दो कॉलम यह गैर परमाणु बनाता है और उस पर आपरेशन का एक बहुत का दोहरीकरण का मतलब है।

ऑडिटीज:

  • कई आधुनिक भाषाओं और प्रणालियों 64 बिट ints लेकिन अहस्ताक्षरित नहीं दे। हस्ताक्षर समस्याग्रस्त है। सकारात्मक संख्या सकारात्मक से कम के रूप में मौजूद है लेकिन उनके बिट अनुक्रम वास्तव में अधिक हैं। इस कारण से 4 * INT UNSIGNED का उपयोग करना आम है।
  • इसी प्रकार लोग इसे उपसर्ग इंडेक्सिंग के लिए तोड़ सकते हैं और आप कम से कम 8 बिट्स (टिन्यिनट अनसिनिड) तक जा सकते हैं। कुछ लोग पूर्ण उपसर्ग इंडेक्सिंग के लिए बीआईटी (1) प्रकार का उपयोग भी कर सकते हैं, माइस्क्लुएल सह पॉजिट इंडेक्स को बिट प्रकारों पर सही तरीके से मानते हैं।
  • फिर से चार स्तंभों के साथ-साथ कुछ ऑपरेशंस जिनके लिए दूसरी ओर ले जाने जैसी चीजों की आवश्यकता होती है, गणना के दौरान ढीले बिट्स के कारण विडंबनात्मक रूप से आसान होती है (गणना में मध्यवर्ती मान अभी भी 64 बिट हो सकते हैं)।

सारांश

लोग विभिन्न कारणों के लिए विभिन्न स्वरूपों का उपयोग करेगा। पिछली संगतता एक कारण हो सकती है और यह आईपीवी 4 के लिए क्या किया जा रहा है इस पर निर्भर करता है। अन्य इस बात पर निर्भर करते हैं कि पते का उपयोग कैसे किया जा रहा है और उसके आस-पास अनुकूलन। आप एक से अधिक दृष्टिकोण का उपयोग कर सकते हैं।

बी 16 एक अच्छा डिफ़ॉल्ट दृष्टिकोण है क्योंकि यह सबसे कुशल और परेशानी रहित है।

PHP में रूपांतरण आप हाथ से उन्हें क्या कर सकते हैं अगर आप अनुसंधान के लिए:

  • जीएमपी या bcmath
  • पीएचपी के नंबर से निपटने और बिटवाइज़ ऑपरेटर्स, पूर्णांक पर सीमाओं की विशेष रूप से पता होना या कार्यों के साथ ही नाव जो उन पर निर्भर करता है जो अन्यथा उपयोगी लग सकते हैं
  • आईपीवी 6 प्रारूप
  • पैक/अनपैक, bin2hex/hex2bin।

हालांकि मैं आईपीवी 6 के विभिन्न डिस्प्ले प्रारूपों से निपटने के लिए एक सामान्य पुस्तकालय का उपयोग करने की सलाह दूंगा।