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

MySQL प्रतिकृति समस्या निवारण:भाग दो

पिछली पोस्ट में, हमने चर्चा की कि कैसे सत्यापित किया जाए कि MySQL प्रतिकृति अच्छी स्थिति में है। हमने कुछ विशिष्ट समस्याओं को भी देखा। इस पोस्ट में, हम कुछ और मुद्दों पर एक नज़र डालेंगे जो आप MySQL प्रतिकृति के साथ काम करते समय देख सकते हैं।

गुम या डुप्लीकेट प्रविष्टियां

यह कुछ ऐसा है जो नहीं होना चाहिए, फिर भी यह बहुत बार होता है - ऐसी स्थिति जिसमें मास्टर पर निष्पादित एक SQL कथन सफल होता है लेकिन दासों में से एक पर निष्पादित एक ही कथन विफल हो जाता है। मुख्य कारण गुलाम बहाव है - कुछ (आमतौर पर गलत लेनदेन लेकिन प्रतिकृति में अन्य मुद्दे या बग) दास को उसके मालिक से अलग करने का कारण बनता है। उदाहरण के लिए, मास्टर पर मौजूद एक पंक्ति दास पर मौजूद नहीं है और इसे हटाया या अद्यतन नहीं किया जा सकता है। यह समस्या कितनी बार दिखाई देती है यह ज्यादातर आपकी प्रतिकृति सेटिंग्स पर निर्भर करता है। संक्षेप में, MySQL बाइनरी लॉग इवेंट को स्टोर करने के तीन तरीके हैं। सबसे पहले, "कथन" का अर्थ है कि एसक्यूएल सादे पाठ में लिखा गया है, जैसे इसे मास्टर पर निष्पादित किया गया है। इस सेटिंग में दास बहाव पर सबसे अधिक सहनशीलता है, लेकिन यह वह भी है जो दास स्थिरता की गारंटी नहीं दे सकता है - इसे उत्पादन में उपयोग करने की अनुशंसा करना कठिन है। दूसरा प्रारूप, "पंक्ति", क्वेरी स्टेटमेंट के बजाय क्वेरी परिणाम संग्रहीत करता है। उदाहरण के लिए, कोई ईवेंट नीचे जैसा दिखाई दे सकता है:

### UPDATE `test`.`tab`
### WHERE
###   @1=2
###   @2=5
### SET
###   @1=2
###   @2=4

इसका मतलब है कि हम 'टैब' तालिका में 'टेस्ट' स्कीमा में एक पंक्ति को अपडेट कर रहे हैं जहां पहले कॉलम का मान 2 है और दूसरे कॉलम का मान 5 है। हम पहले कॉलम को 2 पर सेट करते हैं (मान नहीं बदलता है) और दूसरा कॉलम टू 4. जैसा कि आप देख सकते हैं, व्याख्या के लिए बहुत जगह नहीं है - यह सटीक रूप से परिभाषित है कि कौन सी पंक्ति का उपयोग किया जाता है और इसे कैसे बदला जाता है। नतीजतन, यह प्रारूप दास स्थिरता के लिए बहुत अच्छा है, लेकिन जैसा कि आप कल्पना कर सकते हैं, जब डेटा बहाव की बात आती है तो यह बहुत कमजोर होता है। फिर भी यह MySQL प्रतिकृति चलाने का अनुशंसित तरीका है।

अंत में, तीसरा, "मिश्रित", इस तरह से काम करता है कि वे घटनाएँ जो कथनों के रूप में लिखने के लिए सुरक्षित हैं, "कथन" प्रारूप का उपयोग करती हैं। जो डेटा बहाव का कारण बन सकते हैं वे "पंक्ति" प्रारूप का उपयोग करेंगे।

आप उनका पता कैसे लगाते हैं?

हमेशा की तरह, SHOW SLAVE STATUS समस्या की पहचान करने में हमारी मदद करेगा।

               Last_SQL_Errno: 1032
               Last_SQL_Error: Could not execute Update_rows event on table test.tab; Can't find record in 'tab', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log binlog.000021, end_log_pos 970
               Last_SQL_Errno: 1062
               Last_SQL_Error: Could not execute Write_rows event on table test.tab; Duplicate entry '3' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log binlog.000021, end_log_pos 1229

जैसा कि आप देख सकते हैं, त्रुटियां स्पष्ट और आत्म-व्याख्यात्मक हैं (और वे मूल रूप से MySQL और MariaDB के बीच समान हैं।

आप समस्या को कैसे ठीक करते हैं?

यह दुर्भाग्य से जटिल हिस्सा है। सबसे पहले, आपको सत्य के स्रोत की पहचान करने की आवश्यकता है। किस होस्ट में सही डेटा होता है? मालिक या गुलाम? आमतौर पर आप मान लेते हैं कि यह मास्टर है, लेकिन इसे डिफ़ॉल्ट रूप से न मानें - जांच करें! यह हो सकता है कि फेलओवर के बाद, जारी किए गए आवेदन का कुछ हिस्सा अभी भी पुराने मास्टर को लिखता है, जो अब एक दास के रूप में कार्य करता है। यह हो सकता है कि उस होस्ट पर read_only सही ढंग से सेट नहीं किया गया हो या हो सकता है कि एप्लिकेशन डेटाबेस से कनेक्ट करने के लिए सुपरयुसर का उपयोग करता हो (हां, हमने इसे उत्पादन वातावरण में देखा है)। ऐसे मामले में, दास सत्य का स्रोत हो सकता है - कम से कम कुछ हद तक।

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

           Retrieved_Gtid_Set: 5d1e2227-07c6-11e7-8123-080027495a77:1106672
            Executed_Gtid_Set: 5d1e2227-07c6-11e7-8123-080027495a77:1-1106671

जैसा कि आप देख सकते हैं, हम एक घटना को याद करते हैं:5d1e2227-07c6-11e7-8123-080027495a77:1106672। आइए इसे मास्टर के बाइनरी लॉग में देखें:

mysqlbinlog -v --include-gtids='5d1e2227-07c6-11e7-8123-080027495a77:1106672' /var/lib/mysql/binlog.000021
#170320 20:53:37 server id 1  end_log_pos 1066 CRC32 0xc582a367     GTID    last_committed=3    sequence_number=4
SET @@SESSION.GTID_NEXT= '5d1e2227-07c6-11e7-8123-080027495a77:1106672'/*!*/;
# at 1066
#170320 20:53:37 server id 1  end_log_pos 1138 CRC32 0x6f33754d     Query    thread_id=5285    exec_time=0    error_code=0
SET TIMESTAMP=1490043217/*!*/;
SET @@session.pseudo_thread_id=5285/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 1138
#170320 20:53:37 server id 1  end_log_pos 1185 CRC32 0xa00b1f59     Table_map: `test`.`tab` mapped to number 571
# at 1185
#170320 20:53:37 server id 1  end_log_pos 1229 CRC32 0x5597e50a     Write_rows: table id 571 flags: STMT_END_F

BINLOG '
UUHQWBMBAAAALwAAAKEEAAAAADsCAAAAAAEABHRlc3QAA3RhYgACAwMAAlkfC6A=
UUHQWB4BAAAALAAAAM0EAAAAADsCAAAAAAEAAgAC//wDAAAABwAAAArll1U=
'/*!*/;
### INSERT INTO `test`.`tab`
### SET
###   @1=3
###   @2=7
# at 1229
#170320 20:53:37 server id 1  end_log_pos 1260 CRC32 0xbbc3367c     Xid = 5224257
COMMIT/*!*/;

हम देख सकते हैं कि यह एक इंसर्ट था जो पहले कॉलम को 3 और दूसरे को 7 पर सेट करता है। आइए सत्यापित करें कि हमारी तालिका अब कैसी दिखती है:

mysql> SELECT * FROM test.tab;
+----+------+
| id | b    |
+----+------+
|  1 |    2 |
|  2 |    4 |
|  3 |   10 |
+----+------+
3 rows in set (0.01 sec)

अब हमारे पास दो विकल्प हैं, जिसके आधार पर डेटा प्रबल होना चाहिए। यदि मास्टर पर सही डेटा है, तो हम दास पर आईडी =3 के साथ पंक्ति को आसानी से हटा सकते हैं। गलत लेनदेन शुरू करने से बचने के लिए बस सुनिश्चित करें कि आपने बाइनरी लॉगिंग को अक्षम कर दिया है। दूसरी ओर, यदि हमने तय किया है कि दास पर सही डेटा है, तो हमें वर्तमान (3, 7) की सामग्री (3, 10) को सही करने के लिए आईडी =3 के साथ पंक्ति सेट करने के लिए मास्टर पर REPLACE कमांड चलाने की आवश्यकता है। दास पर, हालांकि, प्रतिकृति को फिर से शुरू करने में सक्षम होने के लिए, हमें वर्तमान GTID को छोड़ना होगा (या, अधिक सटीक होने के लिए, हमें एक खाली GTID ईवेंट बनाना होगा)।

दास पर एक पंक्ति हटाना आसान है:

SET SESSION log_bin=0; DELETE FROM test.tab WHERE id=3; SET SESSION log_bin=1;

खाली GTID डालना लगभग उतना ही सरल है:

mysql> SET @@SESSION.GTID_NEXT= '5d1e2227-07c6-11e7-8123-080027495a77:1106672';
Query OK, 0 rows affected (0.00 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> SET @@SESSION.GTID_NEXT=automatic;
Query OK, 0 rows affected (0.00 sec)

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

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

ClusterControl आपको मास्टर डेटा की एक नई कॉपी का उपयोग करके एक गुलाम को फिर से बनाने की अनुमति देता है।

संगति जांच

जैसा कि हमने पिछले अध्याय में उल्लेख किया है, स्थिरता एक गंभीर समस्या बन सकती है और MySQL प्रतिकृति सेटअप चलाने वाले उपयोगकर्ताओं के लिए बहुत सारे सिरदर्द पैदा कर सकती है। आइए देखें कि आप कैसे सत्यापित कर सकते हैं कि आपके MySQL दास मास्टर के साथ समन्वयित हैं और आप इसके बारे में क्या कर सकते हैं।

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

दुर्भाग्य से, उपयोगकर्ता को यह जानने का सामान्य तरीका है कि दास असंगत है, पिछले अध्याय में हमने जिन मुद्दों का उल्लेख किया है उनमें से एक में भाग लेना है। इससे बचने के लिए दास संगति की सक्रिय निगरानी की आवश्यकता है। आइए देखें कि यह कैसे किया जा सकता है।

हम Percona टूलकिट से एक टूल का उपयोग करने जा रहे हैं:pt-table-checksum। इसे प्रतिकृति क्लस्टर को स्कैन करने और किसी भी विसंगति की पहचान करने के लिए डिज़ाइन किया गया है।

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

--- pt-table-checksum    2016-12-15 14:31:07.000000000 +0000
+++ pt-table-checksum-fix    2017-03-21 20:32:53.282254794 +0000
@@ -7614,7 +7614,7 @@

    my $filter = $self->{filters};

-   if ( $db =~ m/information_schema|performance_schema|lost\+found|percona|percona_schema|test/ ) {
+   if ( $db =~ m/information_schema|performance_schema|lost\+found|percona|percona_schema|^test/ ) {
       PTDEBUG && _d('Database', $db, 'is a system database, ignoring');
       return 0;
    }

सबसे पहले, हम निम्नलिखित तरीके से पीटी-टेबल-चेकसम निष्पादित करने जा रहे हैं:

master:~# ./pt-table-checksum  --max-lag=5 --user=sbtest --password=sbtest --no-check-binlog-format --databases='sbtest'
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
03-21T20:33:30      0      0  1000000      15       0  27.103 sbtest.sbtest1
03-21T20:33:57      0      1  1000000      17       0  26.785 sbtest.sbtest2
03-21T20:34:26      0      0  1000000      15       0  28.503 sbtest.sbtest3
03-21T20:34:52      0      0  1000000      18       0  26.021 sbtest.sbtest4
03-21T20:35:34      0      0  1000000      17       0  42.730 sbtest.sbtest5
03-21T20:36:04      0      0  1000000      16       0  29.309 sbtest.sbtest6
03-21T20:36:42      0      0  1000000      15       0  38.071 sbtest.sbtest7
03-21T20:37:16      0      0  1000000      12       0  33.737 sbtest.sbtest8

हमने टूल को कैसे लागू किया, इस पर कुछ महत्वपूर्ण नोट्स। सबसे पहले, हमारे द्वारा सेट किया गया उपयोगकर्ता सभी दासों पर मौजूद होना चाहिए। यदि आप चाहें, तो आप दासों तक पहुँचने के लिए अन्य, कम विशेषाधिकार प्राप्त उपयोगकर्ता को परिभाषित करने के लिए '--slave-user' का भी उपयोग कर सकते हैं। एक और बात समझाने लायक है - हम पंक्ति-आधारित प्रतिकृति का उपयोग करते हैं जो पीटी-टेबल-चेकसम के साथ पूरी तरह से संगत नहीं है। यदि आपके पास पंक्ति-आधारित प्रतिकृति है, तो क्या होता है पीटी-टेबल-चेकसम सत्र स्तर पर बाइनरी लॉग प्रारूप को 'स्टेटमेंट' में बदल देगा क्योंकि यह एकमात्र समर्थित प्रारूप है। समस्या यह है कि ऐसा परिवर्तन केवल पहले स्तर के दासों पर ही काम करेगा जो सीधे मालिक से जुड़े होते हैं। यदि आपके पास मध्यवर्ती स्वामी हैं (इसलिए, दासों के एक से अधिक स्तर), तो पीटी-टेबल-चेकसम का उपयोग करने से प्रतिकृति टूट सकती है। यही कारण है कि, डिफ़ॉल्ट रूप से, यदि उपकरण पंक्ति-आधारित प्रतिकृति का पता लगाता है, तो यह बाहर निकल जाता है और त्रुटि प्रिंट करता है:

"प्रतिकृति दास 1 में binlog_format ROW है जो पीटी-टेबल-चेकसम को प्रतिकृति तोड़ने का कारण बन सकता है। कृपया टूल के दस्तावेज़ीकरण के LIMITATIONS अनुभाग में "पंक्ति-आधारित प्रतिकृति का उपयोग करते हुए प्रतिकृतियां" पढ़ें। यदि आप जोखिमों को समझते हैं, तो इस चेक को अक्षम करने के लिए --no-check-binlog-format निर्दिष्ट करें।"

हमने दासों के केवल एक स्तर का उपयोग किया था इसलिए "--no-check-binlog-format" निर्दिष्ट करना और आगे बढ़ना सुरक्षित था।

अंत में, हम अधिकतम अंतराल को 5 सेकंड पर सेट करते हैं। अगर इस सीमा तक पहुंच जाएगा, तो पीटी-टेबल-चेकसम अंतराल को थ्रेशोल्ड के नीचे लाने के लिए आवश्यक समय के लिए रुक जाएगा।

जैसा कि आप आउटपुट से देख सकते हैं,

03-21T20:33:57      0      1  1000000      17       0  26.785 sbtest.sbtest2

तालिका sbtest.sbtest2 पर एक विसंगति पाई गई है।

डिफ़ॉल्ट रूप से, पीटी-टेबल-चेकसम चेकसम को percona.checksums तालिका में संग्रहीत करता है। डेटा में सटीक अंतर खोजने के लिए तालिका के किन हिस्सों की विस्तार से जाँच की जानी चाहिए, इसकी पहचान करने के लिए इस डेटा का उपयोग Percona टूलकिट, pt-table-sync से दूसरे टूल के लिए किया जा सकता है।

असंगत दास को कैसे ठीक करें

जैसा कि ऊपर उल्लेख किया गया है, हम ऐसा करने के लिए पीटी-टेबल-सिंक का उपयोग करेंगे। हमारे मामले में हम पीटी-टेबल-चेकसम द्वारा एकत्र किए गए डेटा का उपयोग करने जा रहे हैं, हालांकि पीटी-टेबल-सिंक को दो मेजबानों (मास्टर और एक दास) को इंगित करना भी संभव है और यह दोनों मेजबानों के सभी डेटा की तुलना करेगा। यह निश्चित रूप से अधिक समय और संसाधन लेने वाली प्रक्रिया है, इसलिए जब तक आपके पास पहले से ही पीटी-टेबल-चेकसम से डेटा है, इसका उपयोग करना बेहतर है। आउटपुट का परीक्षण करने के लिए हमने इसे इस तरह निष्पादित किया:

master:~# ./pt-table-sync --user=sbtest --password=sbtest --databases=sbtest --replicate percona.checksums h=master --print
REPLACE INTO `sbtest`.`sbtest2`(`id`, `k`, `c`, `pad`) VALUES ('1', '434041', '61753673565-14739672440-12887544709-74227036147-86382758284-62912436480-22536544941-50641666437-36404946534-73544093889', '23608763234-05826685838-82708573685-48410807053-00139962956') /*percona-toolkit src_db:sbtest src_tbl:sbtest2 src_dsn:h=10.0.0.101,p=...,u=sbtest dst_db:sbtest dst_tbl:sbtest2 dst_dsn:h=10.0.0.103,p=...,u=sbtest lock:1 transaction:1 changing_src:percona.checksums replicate:percona.checksums bidirectional:0 pid:25776 user:root host:vagrant-ubuntu-trusty-64*/;

जैसा कि आप देख सकते हैं, परिणामस्वरूप कुछ SQL उत्पन्न हुए हैं। नोट करने के लिए महत्वपूर्ण है --replicate वेरिएबल। यहां क्या होता है हम पीटी-टेबल-सिंक को पीटी-टेबल-चेकसम द्वारा उत्पन्न तालिका में इंगित करते हैं। हम इसे मास्टर की ओर भी इशारा करते हैं।

यह सत्यापित करने के लिए कि क्या SQL समझ में आता है, हमने --प्रिंट विकल्प का उपयोग किया। कृपया ध्यान दें कि उत्पन्न SQL केवल उस समय मान्य होता है जब वह उत्पन्न होता है - आप वास्तव में इसे कहीं संग्रहीत नहीं कर सकते, इसकी समीक्षा कर सकते हैं और फिर निष्पादित कर सकते हैं। आप बस इतना कर सकते हैं कि यह सत्यापित करें कि क्या SQL का कोई अर्थ है और, इसके तुरंत बाद, --execute ध्वज के साथ टूल को फिर से निष्पादित करें:

master:~# ./pt-table-sync --user=sbtest --password=sbtest --databases=sbtest --replicate percona.checksums h=10.0.0.101 --execute

यह दास को स्वामी के साथ वापस सिंक कर देना चाहिए। हम इसे पीटी-टेबल-चेकसम से सत्यापित कर सकते हैं:

[email protected]:~# ./pt-table-checksum  --max-lag=5 --user=sbtest --password=sbtest --no-check-binlog-format --databases='sbtest'
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
03-21T21:36:04      0      0  1000000      13       0  23.749 sbtest.sbtest1
03-21T21:36:26      0      0  1000000       7       0  22.333 sbtest.sbtest2
03-21T21:36:51      0      0  1000000      10       0  24.780 sbtest.sbtest3
03-21T21:37:11      0      0  1000000      14       0  19.782 sbtest.sbtest4
03-21T21:37:42      0      0  1000000      15       0  30.954 sbtest.sbtest5
03-21T21:38:07      0      0  1000000      15       0  25.593 sbtest.sbtest6
03-21T21:38:27      0      0  1000000      16       0  19.339 sbtest.sbtest7
03-21T21:38:44      0      0  1000000      15       0  17.371 sbtest.sbtest8

जैसा कि आप देख सकते हैं, sbtest.sbtest2 तालिका में अब कोई अंतर नहीं है।

हमें उम्मीद है कि आपको यह ब्लॉग पोस्ट जानकारीपूर्ण और उपयोगी लगी होगी। MySQL प्रतिकृति के बारे में अधिक जानने के लिए यहां क्लिक करें। यदि आपके कोई प्रश्न या सुझाव हैं, तो नीचे टिप्पणी के माध्यम से हमसे बेझिझक संपर्क करें।


  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. पीडीओ परीक्षण करने के लिए PHP कोड उपलब्ध है?

  4. PhpMyAdmin का उपयोग करके डेटाबेस कैसे आयात करें

  5. MySQL डेटाबेस के लिए दूरस्थ पहुँच सक्षम करें