Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

MySQL प्रतिकृति और GTID- आधारित विफलता - त्रुटिपूर्ण लेन-देन में एक गहरा गोता

सालों से, MySQL प्रतिकृति बाइनरी लॉग इवेंट्स पर आधारित होती थी - एक दास को पता था कि वह सटीक घटना और सटीक स्थिति थी जिसे उसने अभी मास्टर से पढ़ा था। मास्टर से कोई भी एकल लेनदेन अलग-अलग बाइनरी लॉग में समाप्त हो सकता है, और इन लॉग में अलग-अलग स्थिति में हो सकता है। यह एक सरल समाधान था जो सीमाओं के साथ आया था - अधिक जटिल टोपोलॉजी परिवर्तनों में शामिल मेजबानों पर प्रतिकृति को रोकने के लिए एक व्यवस्थापक की आवश्यकता हो सकती है। या ये परिवर्तन कुछ अन्य मुद्दों का कारण बन सकते हैं, उदाहरण के लिए, एक दास को समय लेने वाली पुनर्निर्माण प्रक्रिया के बिना प्रतिकृति श्रृंखला में नीचे नहीं ले जाया जा सकता है (हम आसानी से ए -> बी -> सी से ए -> सी से प्रतिकृति को आसानी से नहीं बदल सकते हैं।> बी बी और सी दोनों पर प्रतिकृति को रोके बिना)। वैश्विक लेन-देन पहचानकर्ता का सपना देखते हुए हम सभी को इन सीमाओं के आसपास काम करना पड़ा है।

GTID को MySQL 5.6 के साथ पेश किया गया था, और MySQL के संचालन के तरीके में कुछ बड़े बदलाव लाए। सबसे पहले, प्रत्येक लेनदेन में एक विशिष्ट पहचानकर्ता होता है जो इसे प्रत्येक सर्वर पर उसी तरह पहचानता है। यह अब महत्वपूर्ण नहीं है कि लेन-देन किस बाइनरी लॉग स्थिति में दर्ज किया गया था, आपको केवल GTID जानने की आवश्यकता है:'966073f3-b6a4-11e4-af2c-080027880ca6:4'। GTID को दो भागों से बनाया गया है - एक सर्वर का विशिष्ट पहचानकर्ता जहां पहली बार लेन-देन किया गया था, और एक अनुक्रम संख्या। उपरोक्त उदाहरण में, हम देख सकते हैं कि लेनदेन सर्वर द्वारा '966073f3-b6a4-11e4-af2c-080027880ca6' के सर्वर_यूयूआईडी के साथ निष्पादित किया गया था और यह वहां निष्पादित चौथा लेनदेन है। यह जानकारी जटिल टोपोलॉजी परिवर्तन करने के लिए पर्याप्त है - MySQL जानता है कि कौन से लेनदेन निष्पादित किए गए हैं और इसलिए यह जानता है कि कौन से लेनदेन को आगे निष्पादित करने की आवश्यकता है। बाइनरी लॉग के बारे में भूल जाइए, यह सब GTID में है।

तो, आपको GTID कहां मिल सकता है? आप उन्हें दो जगहों पर पाएंगे। एक गुलाम पर, 'गुलाम की स्थिति दिखाएं' में आपको दो कॉलम मिलेंगे:Retrieved_Gtid_Set और Executed_Gtid_Set। पहला GTID को कवर करता है जिसे प्रतिकृति के माध्यम से मास्टर से पुनर्प्राप्त किया गया था, दूसरा उन सभी लेनदेन के बारे में सूचित करता है जो दिए गए होस्ट पर निष्पादित किए गए थे - दोनों प्रतिकृति के माध्यम से या स्थानीय रूप से निष्पादित।

प्रतिकृति क्लस्टर को आसान तरीके से सेट करना

ClusterControl में MySQL प्रतिकृति क्लस्टर का परिनियोजन बहुत आसान है (आप इसे मुफ्त में आज़मा सकते हैं)। एकमात्र शर्त यह है कि सभी होस्ट, जिनका उपयोग आप MySQL नोड्स को परिनियोजित करने के लिए करेंगे, को ClusterControl इंस्टेंस से पासवर्ड रहित SSH कनेक्शन का उपयोग करके एक्सेस किया जा सकता है।

जब कनेक्टिविटी मौजूद हो, तो आप "तैनाती" विकल्प का उपयोग करके क्लस्टर को परिनियोजित कर सकते हैं। जब विज़ार्ड विंडो खुली होती है, तो आपको कुछ निर्णय लेने होते हैं - आप क्या करना चाहते हैं? एक नया क्लस्टर तैनात करें? Postgresql नोड परिनियोजित करें या मौजूदा क्लस्टर आयात करें।

हम एक नया क्लस्टर तैनात करना चाहते हैं। फिर हमें निम्नलिखित स्क्रीन के साथ प्रस्तुत किया जाएगा जिसमें हमें यह तय करने की आवश्यकता है कि हम किस प्रकार का क्लस्टर तैनात करना चाहते हैं। आइए प्रतिकृति चुनें और फिर ssh कनेक्टिविटी के बारे में आवश्यक विवरण पास करें।

तैयार होने पर, जारी रखें पर क्लिक करें। इस बार हमें यह तय करने की आवश्यकता है कि हम किस MySQL विक्रेता का उपयोग करना चाहते हैं, कौन सा संस्करण और कुछ कॉन्फ़िगरेशन सेटिंग्स, जिनमें अन्य शामिल हैं, MySQL में रूट खाते के लिए पासवर्ड।

अंत में, हमें प्रतिकृति टोपोलॉजी पर निर्णय लेने की आवश्यकता है - आप या तो एक विशिष्ट मास्टर - गुलाम सेटअप का उपयोग कर सकते हैं या अधिक जटिल, सक्रिय - स्टैंडबाय मास्टर - मास्टर जोड़ी बना सकते हैं (+ दास जो आप उन्हें जोड़ना चाहते हैं)। एक बार तैयार होने के बाद, बस "तैनाती" पर क्लिक करें और कुछ ही मिनटों में आपको अपना क्लस्टर तैनात कर देना चाहिए।

एक बार यह हो जाने के बाद, आप अपने क्लस्टर को ClusterControl के UI की क्लस्टर सूची में देखेंगे।

प्रतिकृति तैयार करने और चलाने के बाद हम इस पर करीब से नज़र डाल सकते हैं कि GTID कैसे काम करता है।

गलत लेनदेन - समस्या क्या है?

जैसा कि हमने इस पोस्ट की शुरुआत में उल्लेख किया है, GTID ने लोगों के MySQL प्रतिकृति के बारे में सोचने के तरीके में एक महत्वपूर्ण बदलाव लाया है। यह सब आदतों के बारे में है। मान लीजिए, किसी कारण से, एक आवेदन ने दासों में से एक पर लिखा। ऐसा नहीं होना चाहिए था लेकिन हैरानी की बात यह है कि यह हर समय होता है। नतीजतन, डुप्लिकेट कुंजी त्रुटि के साथ प्रतिकृति बंद हो जाती है। ऐसी समस्या से निपटने के दो तरीके हैं। उनमें से एक आपत्तिजनक पंक्ति को हटाना और प्रतिकृति को फिर से शुरू करना होगा। दूसरा यह होगा कि बाइनरी लॉग इवेंट को छोड़ दें और फिर प्रतिकृति को फिर से शुरू करें।

STOP SLAVE SQL_THREAD; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE SQL_THREAD;

दोनों तरीकों से प्रतिकृति को काम पर वापस लाया जाना चाहिए, लेकिन वे डेटा बहाव को पेश कर सकते हैं, इसलिए यह याद रखना आवश्यक है कि इस तरह की घटना के बाद दास स्थिरता की जांच की जानी चाहिए (पीटी-टेबल-चेकसम और पीटी-टेबल-सिंक यहां अच्छी तरह से काम करता है)।

यदि GTID का उपयोग करते समय भी ऐसी ही समस्या होती है, तो आपको कुछ अंतर दिखाई देंगे। आपत्तिजनक पंक्ति को हटाने से समस्या ठीक हो सकती है, प्रतिकृति शुरू करने में सक्षम होना चाहिए। दूसरी विधि, sql_slave_skip_counter का उपयोग करना बिल्कुल भी काम नहीं करेगा - यह एक त्रुटि लौटाएगा। याद रखें, यह अब बिनलॉग ईवेंट के बारे में नहीं है, यह GTID के निष्पादित होने या न होने के बारे में है।

समस्या को ठीक करने के लिए पंक्ति को हटाना केवल 'लगता है' क्यों? जीटीआईडी ​​​​के संबंध में ध्यान रखने वाली सबसे महत्वपूर्ण बातों में से एक यह है कि एक गुलाम, मास्टर से कनेक्ट होने पर, यह जांचता है कि क्या मास्टर पर निष्पादित कोई भी लेनदेन गायब है या नहीं। इन्हें गलत लेनदेन कहा जाता है। यदि किसी दास को ऐसे लेन-देन मिलते हैं, तो वह उन्हें निष्पादित करेगा। मान लें कि हम एक आपत्तिजनक पंक्ति को साफ़ करने के लिए SQL का अनुसरण कर रहे हैं:

DELETE FROM mytable WHERE id=100;

आइए देखें गुलाम की स्थिति दिखाएं:

                  Master_UUID: 966073f3-b6a4-11e4-af2c-080027880ca6
           Retrieved_Gtid_Set: 966073f3-b6a4-11e4-af2c-080027880ca6:1-29
            Executed_Gtid_Set: 84d15910-b6a4-11e4-af2c-080027880ca6:1,
966073f3-b6a4-11e4-af2c-080027880ca6:1-29,

और देखें कि 84d15910-b6a4-11e4-af2c-080027880ca6:1 कहां से आता है:

mysql> SHOW VARIABLES LIKE 'server_uuid'\G
*************************** 1. row ***************************
Variable_name: server_uuid
        Value: 84d15910-b6a4-11e4-af2c-080027880ca6
1 row in set (0.00 sec)

जैसा कि आप देख सकते हैं, हमारे पास 29 लेनदेन हैं जो मास्टर से आए हैं, UUID का 966073f3-b6a4-11e4-af2c-080027880ca6 और एक जिसे स्थानीय रूप से निष्पादित किया गया था। मान लीजिए कि किसी बिंदु पर हम विफल हो जाते हैं और मास्टर (966073f3-b6a4-11e4-af2c-080027880ca6) गुलाम बन जाता है। यह निष्पादित GTID की अपनी सूची की जाँच करेगा और इसे यह नहीं मिलेगा:84d15910-b6a4-11e4-af2c-080027880ca6:1। परिणामस्वरूप, संबंधित SQL निष्पादित किया जाएगा:

DELETE FROM mytable WHERE id=100;

यह ऐसी चीज नहीं है जिसकी हमें उम्मीद थी... यदि इस बीच, इस लेन-देन वाले बिनलॉग को पुराने दास पर शुद्ध कर दिया जाएगा, तो नया दास विफलता के बाद शिकायत करेगा:

                Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'

गलत लेनदेन का पता कैसे लगाएं?

जब आप अलग-अलग होस्ट पर GTID सेट की तुलना करना चाहते हैं तो MySQL दो फ़ंक्शन प्रदान करता है जो बहुत काम आते हैं।

GTID_SUBSET() दो GTID सेट लेता है और जांचता है कि पहला सेट दूसरे सेट का सबसेट है या नहीं।

मान लें कि हमारे पास निम्नलिखित राज्य है।

मास्टर:

mysql> show master status\G
*************************** 1. row ***************************
             File: binlog.000002
         Position: 160205927
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: 8a6962d2-b907-11e4-bebc-080027880ca6:1-153,
9b09b44a-b907-11e4-bebd-080027880ca6:1,
ab8f5793-b907-11e4-bebd-080027880ca6:1-2
1 row in set (0.00 sec)

गुलाम:

mysql> show slave status\G
[...]
           Retrieved_Gtid_Set: 8a6962d2-b907-11e4-bebc-080027880ca6:1-153,
9b09b44a-b907-11e4-bebd-080027880ca6:1
            Executed_Gtid_Set: 8a6962d2-b907-11e4-bebc-080027880ca6:1-153,
9b09b44a-b907-11e4-bebd-080027880ca6:1,
ab8f5793-b907-11e4-bebd-080027880ca6:1-4

हम निम्न SQL को निष्पादित करके जांच सकते हैं कि क्या दास के पास कोई गलत लेनदेन है:

mysql> SELECT GTID_SUBSET('8a6962d2-b907-11e4-bebc-080027880ca6:1-153,ab8f5793-b907-11e4-bebd-080027880ca6:1-4', '8a6962d2-b907-11e4-bebc-080027880ca6:1-153, 9b09b44a-b907-11e4-bebd-080027880ca6:1, ab8f5793-b907-11e4-bebd-080027880ca6:1-2') as is_subset\G
*************************** 1. row ***************************
is_subset: 0
1 row in set (0.00 sec)

ऐसा लगता है कि गलत लेनदेन हो रहे हैं। हम उन्हें कैसे पहचानते हैं? हम एक अन्य फ़ंक्शन का उपयोग कर सकते हैं, GTID_SUBTRACT()

mysql> SELECT GTID_SUBTRACT('8a6962d2-b907-11e4-bebc-080027880ca6:1-153,ab8f5793-b907-11e4-bebd-080027880ca6:1-4', '8a6962d2-b907-11e4-bebc-080027880ca6:1-153, 9b09b44a-b907-11e4-bebd-080027880ca6:1, ab8f5793-b907-11e4-bebd-080027880ca6:1-2') as mising\G
*************************** 1. row ***************************
mising: ab8f5793-b907-11e4-bebd-080027880ca6:3-4
1 row in set (0.01 sec)

हमारे लापता GTID हैं ab8f5793-b907-11e4-bebd-080027880ca6:3-4 - वे लेन-देन दास पर निष्पादित किए गए थे लेकिन मास्टर पर नहीं।

गलत लेनदेन के कारण होने वाली समस्याओं का समाधान कैसे करें?

दो तरीके हैं - खाली लेन-देन इंजेक्ट करें या GTID इतिहास से लेनदेन को बाहर करें।

खाली लेनदेन को इंजेक्ट करने के लिए हम निम्नलिखित SQL का उपयोग कर सकते हैं:

mysql> SET gtid_next='ab8f5793-b907-11e4-bebd-080027880ca6:3';
Query OK, 0 rows affected (0.01 sec)
mysql> begin ; commit;
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.01 sec)
mysql> SET gtid_next='ab8f5793-b907-11e4-bebd-080027880ca6:4';
Query OK, 0 rows affected (0.00 sec)
mysql> begin ; commit;
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.01 sec)
mysql> SET gtid_next=automatic;
Query OK, 0 rows affected (0.00 sec)

इसे प्रतिकृति टोपोलॉजी में प्रत्येक होस्ट पर निष्पादित किया जाना है, जिसमें उन GTID को निष्पादित नहीं किया गया है। यदि मास्टर उपलब्ध है, तो आप उन लेन-देन को वहां इंजेक्ट कर सकते हैं और उन्हें श्रृंखला को दोहराने दे सकते हैं। यदि मास्टर उपलब्ध नहीं है (उदाहरण के लिए, यह दुर्घटनाग्रस्त हो गया), तो उन खाली लेनदेन को प्रत्येक दास पर निष्पादित करना होगा। Oracle ने mysqlslavetrx नामक एक उपकरण विकसित किया है जिसे इस प्रक्रिया को स्वचालित करने के लिए डिज़ाइन किया गया है।

एक और तरीका है GTID को इतिहास से हटाना:

बंद करो गुलाम:

mysql> STOP SLAVE;

Executed_Gtid_Set को स्लेव पर प्रिंट करें:

mysql> SHOW MASTER STATUS\G

GTID जानकारी रीसेट करें:

RESET MASTER;

GTID_PURGED को सही GTID सेट पर सेट करें। SHOW MASTER STATUS के डेटा के आधार पर। आपको गलत लेन-देन को सेट से बाहर कर देना चाहिए।

SET GLOBAL GTID_PURGED='8a6962d2-b907-11e4-bebc-080027880ca6:1-153, 9b09b44a-b907-11e4-bebd-080027880ca6:1, ab8f5793-b907-11e4-bebd-080027880ca6:1-2';

दास प्रारंभ करें।

mysql> START SLAVE\G

हर मामले में, आपको पीटी-टेबल-चेकसम और पीटी-टेबल-सिंक (यदि आवश्यक हो) का उपयोग करके अपने दासों की संगति को सत्यापित करना चाहिए - गलत लेनदेन के परिणामस्वरूप डेटा बहाव हो सकता है।

ClusterControl में विफलता

संस्करण 1.4 से शुरू होकर, ClusterControl ने MySQL प्रतिकृति के लिए अपनी विफलता प्रबंधन प्रक्रियाओं को बढ़ाया है। आप अभी भी एक दास को मास्टर में बढ़ावा देकर मैन्युअल मास्टर स्विच कर सकते हैं। फिर शेष दास नए स्वामी के सामने असफल हो जाएँगे। संस्करण 1.4 से, ClusterControl में मास्टर के विफल होने पर पूरी तरह से स्वचालित फ़ेलओवर करने की क्षमता भी है। हमने ClusterControl और स्वचालित विफलता का वर्णन करते हुए एक ब्लॉग पोस्ट में इसे गहराई से कवर किया है। हम अभी भी इस पोस्ट के विषय से सीधे संबंधित एक विशेषता का उल्लेख करना चाहेंगे।

डिफ़ॉल्ट रूप से, ClusterControl फेलओवर को "सुरक्षित तरीके" से करता है - फेलओवर के समय (या स्विचओवर, यदि यह उपयोगकर्ता है जिसने मास्टर स्विच निष्पादित किया है), ClusterControl एक मास्टर उम्मीदवार चुनता है और फिर सत्यापित करता है कि इस नोड में कोई गलत लेनदेन नहीं है जो मास्टर बनने के बाद प्रतिकृति को प्रभावित करेगा। यदि एक गलत लेन-देन का पता चलता है, तो ClusterControl फेलओवर प्रक्रिया को रोक देगा और मास्टर उम्मीदवार को नया मास्टर बनने के लिए पदोन्नत नहीं किया जाएगा।

यदि आप 100% निश्चित होना चाहते हैं कि ClusterControl एक नए मास्टर को बढ़ावा देगा, भले ही कुछ मुद्दों (जैसे गलत लेनदेन) का पता चला हो, तो आप ऐसा कर सकते हैं कि cmon कॉन्फ़िगरेशन में प्रतिकृति_स्टॉप_ऑन_एरर =0 सेटिंग का उपयोग करें। बेशक, जैसा कि हमने चर्चा की, इससे प्रतिकृति के साथ समस्याएं हो सकती हैं - दास एक बाइनरी लॉग इवेंट के लिए पूछना शुरू कर सकते हैं जो अब उपलब्ध नहीं है।

ऐसे मामलों को संभालने के लिए, हमने दास पुनर्निर्माण के लिए प्रयोगात्मक समर्थन जोड़ा। यदि आप cmon कॉन्फ़िगरेशन में प्रतिकृति_ऑटो_रेबिल्ड_स्लेव =1 सेट करते हैं और आपके दास को MySQL में निम्न त्रुटि के साथ नीचे के रूप में चिह्नित किया गया है, तो ClusterControl मास्टर से डेटा का उपयोग करके दास को फिर से बनाने का प्रयास करेगा:

बाइनरी लॉग से डेटा पढ़ते समय मास्टर की ओर से घातक त्रुटि 1236 मिली:'गुलाम CHANGE MASTER TO MASTER_AUTO_POSITION =1 का उपयोग करके कनेक्ट हो रहा है, लेकिन मास्टर ने GTID वाले बाइनरी लॉग को शुद्ध कर दिया है जिसकी दास को आवश्यकता है।'

ऐसी सेटिंग हमेशा उपयुक्त नहीं हो सकती है क्योंकि पुनर्निर्माण प्रक्रिया मास्टर पर बढ़े हुए भार को प्रेरित करेगी। यह भी हो सकता है कि आपका डेटासेट बहुत बड़ा हो और नियमित पुनर्निर्माण कोई विकल्प न हो - इसलिए यह व्यवहार डिफ़ॉल्ट रूप से अक्षम होता है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. टेक्स्ट फ़ाइल से mysql डेटाबेस में डेटा कैसे आयात करें

  2. उच्च उपलब्धता के लिए MySQL के लिए हाइब्रिड क्लाउड प्रतिकृति

  3. MySQL में एक टेबल या कॉलम नाम के रूप में आरक्षित शब्द का उपयोग करने के कारण सिंटैक्स त्रुटि

  4. Mysqli सिंक त्रुटि से कमांड क्यों दे रहा है?

  5. MySQL को तालिका से लापता आईडी मिलती है