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

RSU विधि का उपयोग करके MySQL गैलेरा क्लस्टर में ऑनलाइन स्कीमा अपग्रेड

यह पोस्ट टीओआई पद्धति का उपयोग करके गैलेरा में ऑनलाइन स्कीमा अपग्रेड पर हमारी पिछली पोस्ट की निरंतरता है। अब हम आपको दिखाएंगे कि रोलिंग स्कीमा अपग्रेड (आरएसयू) पद्धति का उपयोग करके स्कीमा अपग्रेड कैसे करें।

आरएसयू और टीओआई

जैसा कि हमने चर्चा की, TOI का उपयोग करते समय, सभी नोड्स पर एक ही समय में परिवर्तन होता है। यह एक गंभीर सीमा बन सकता है क्योंकि स्कीमा परिवर्तनों को क्रियान्वित करने के इस तरीके का तात्पर्य है कि कोई अन्य प्रश्न निष्पादित नहीं किया जा सकता है। लंबे ALTER स्टेटमेंट के लिए, क्लस्टर घंटों तक भी उपलब्ध नहीं हो सकता है। जाहिर है, यह ऐसा कुछ नहीं है जिसे आप उत्पादन में स्वीकार कर सकते हैं। RSU विधि इस कमजोरी को दूर करती है - परिवर्तन एक समय में एक नोड पर होते हैं जबकि अन्य नोड प्रभावित नहीं होते हैं और यातायात की सेवा कर सकते हैं। एक बार जब ALTER एक नोड पर पूरा हो जाता है, तो यह क्लस्टर में फिर से जुड़ जाएगा और आप अगले नोड पर एक स्कीमा परिवर्तन को क्रियान्वित करने के साथ आगे बढ़ सकते हैं।

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

गैलेरा और पंक्ति-आधारित बाइनरी लॉग प्रारूप

ठीक है, तो डीएमएल को पुराने और नए स्कीमा पर काम करना है। डीएमएल को गैलेरा नोड्स के बीच कैसे स्थानांतरित किया जाता है? क्या यह प्रभावित करता है कि कौन से परिवर्तन संगत हैं और क्या नहीं? हाँ, वास्तव में - यह करता है। गैलेरा नियमित MySQL प्रतिकृति का उपयोग नहीं करता है, लेकिन यह अभी भी नोड्स के बीच घटनाओं को स्थानांतरित करने के लिए इस पर निर्भर करता है। सटीक होने के लिए, गैलेरा घटनाओं के लिए आरओडब्ल्यू प्रारूप का उपयोग करता है। पंक्ति प्रारूप में एक घटना (डिकोडिंग के बाद) इस तरह दिख सकती है:

### INSERT INTO `schema`.`table`
### SET
###   @1=1
###   @2=1
###   @3='88764053989'
###   @4='14700597838'

या:

### UPDATE `schema`.`table`
### WHERE
###   @1=1
###   @2=1
###   @3='88764053989'
###   @4='14700597838'
### SET
###   @1=2
###   @2=2
###   @3='88764053989'
###   @4='81084251066'

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

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

आरएसयू उदाहरण

प्रारंभिक सेटअप

आइए एक एप्लिकेशन के बजाय एक सरल उदाहरण की कल्पना करें। हम सामग्री और ट्रैफ़िक उत्पन्न करने के लिए एक बेंचमार्क टूल, Sysbench का उपयोग करेंगे, लेकिन प्रवाह लगभग हर एप्लिकेशन के लिए समान होगा - Wordpress, Joomla, Drupal, आप इसे नाम दें। हम राउंड-रॉबिन फैशन में गैलेरा नोड्स के बीच पढ़ने और लिखने को विभाजित करने के लिए हमारे एप्लिकेशन के साथ HAProxy का उपयोग करेंगे। आप नीचे देख सकते हैं कि HAProxy गैलेरा क्लस्टर को कैसे देखता है।

संपूर्ण टोपोलॉजी नीचे जैसा दिखता है:

निम्न आदेश का उपयोग करके यातायात उत्पन्न होता है:

while true ; do sysbench /root/sysbench/src/lua/oltp_read_write.lua --threads=4 --max-requests=0 --time=3600 --mysql-host=10.0.0.100 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=3307 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable run ; done

स्कीमा नीचे जैसा दिखता है:

mysql> SHOW CREATE TABLE sbtest1.sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=29986632 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

सबसे पहले, आइए देखें कि हम इस तालिका में एक इंडेक्स कैसे जोड़ सकते हैं। अनुक्रमणिका जोड़ना एक संगत परिवर्तन है जिसे RSU का उपयोग करके आसानी से किया जा सकता है।

mysql> SET SESSION wsrep_OSU_method=RSU;
Query OK, 0 rows affected (0.00 sec)
mysql> ALTER TABLE sbtest1.sbtest1 ADD INDEX idx_new (k, c); 
Query OK, 0 rows affected (5 min 19.59 sec)

जैसा कि आप नोड टैब में देख सकते हैं, जिस होस्ट पर हमने परिवर्तन निष्पादित किया है, वह स्वचालित रूप से दाता/डिसिंक्ड स्थिति में स्विच हो गया है जो सुनिश्चित करता है कि यह होस्ट बाकी क्लस्टर को प्रभावित नहीं करेगा यदि यह ALTER द्वारा धीमा हो जाता है।

आइए देखें कि हमारा स्कीमा अब कैसा दिखता है:

mysql> SHOW CREATE TABLE sbtest1.sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`),
  KEY `idx_new` (`k`,`c`)
) ENGINE=InnoDB AUTO_INCREMENT=29986632 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

जैसा कि आप देख सकते हैं, सूचकांक जोड़ा गया है। कृपया ध्यान रखें, हालांकि, यह केवल उस विशेष नोड पर हुआ है। एक पूर्ण स्कीमा परिवर्तन को पूरा करने के लिए, आपको गैलेरा क्लस्टर के शेष नोड्स पर इस प्रक्रिया का पालन करना होगा। पहले नोड के साथ समाप्त करने के लिए, हम wsrep_OSU_method को वापस TOI पर स्विच कर सकते हैं:

SET SESSION wsrep_OSU_method=TOI;
Query OK, 0 rows affected (0.00 sec)

हम शेष प्रक्रिया को नहीं दिखाने जा रहे हैं, क्योंकि यह समान है - सत्र स्तर पर RSU को सक्षम करें, ALTER चलाएँ, TOI को सक्षम करें। क्या अधिक दिलचस्प है यदि परिवर्तन असंगत होगा तो क्या होगा। आइए फिर से स्कीमा पर एक नज़र डालते हैं:

mysql> SHOW CREATE TABLE sbtest1.sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`),
  KEY `idx_new` (`k`,`c`)
) ENGINE=InnoDB AUTO_INCREMENT=29986632 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

मान लें कि हम एक नोड पर कॉलम 'k' के प्रकार को INT से VARCHAR(30) में बदलना चाहते हैं।

mysql> SET SESSION wsrep_OSU_method=RSU;
Query OK, 0 rows affected (0.00 sec)
mysql> ALTER TABLE sbtest1.sbtest1 MODIFY COLUMN k VARCHAR(30) NOT NULL DEFAULT '';
Query OK, 10004785 rows affected (1 hour 14 min 51.89 sec)
Records: 10004785  Duplicates: 0  Warnings: 0

अब, स्कीमा पर एक नज़र डालते हैं:

mysql> SHOW CREATE TABLE sbtest1.sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` varchar(30) NOT NULL DEFAULT '',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`),
  KEY `idx_new` (`k`,`c`)
) ENGINE=InnoDB AUTO_INCREMENT=29986632 DEFAULT CHARSET=latin1
1 row in set (0.02 sec)

सब कुछ वैसा ही है जैसा हम उम्मीद करते हैं - 'k' कॉलम को VARCHAR में बदल दिया गया है। अब हम जांच सकते हैं कि यह परिवर्तन गैलेरा क्लस्टर के लिए स्वीकार्य है या नहीं। इसका परीक्षण करने के लिए, हम निम्नलिखित क्वेरी को निष्पादित करने के लिए शेष, अपरिवर्तित नोड्स में से एक का उपयोग करेंगे:

mysql> INSERT INTO sbtest1.sbtest1 (k, c, pad) VALUES (123, 'test', 'test');
Query OK, 1 row affected (0.19 sec)
देखते है क्या हुआ।

यह निश्चित रूप से अच्छा नहीं लग रहा है - हमारा नोड नीचे है। लॉग आपको अधिक विवरण देंगे:

2017-04-07T10:51:14.873524Z 5 [ERROR] Slave SQL: Column 1 of table 'sbtest1.sbtest1' cannot be converted from type 'int' to type 'varchar(30)', Error_code: 1677
2017-04-07T10:51:14.873560Z 5 [Warning] WSREP: RBR event 3 Write_rows apply warning: 3, 982675
2017-04-07T10:51:14.879120Z 5 [Warning] WSREP: Failed to apply app buffer: seqno: 982675, status: 1
         at galera/src/trx_handle.cpp:apply():351
Retrying 2th time
2017-04-07T10:51:14.879272Z 5 [ERROR] Slave SQL: Column 1 of table 'sbtest1.sbtest1' cannot be converted from type 'int' to type 'varchar(30)', Error_code: 1677
2017-04-07T10:51:14.879287Z 5 [Warning] WSREP: RBR event 3 Write_rows apply warning: 3, 982675
2017-04-07T10:51:14.879399Z 5 [Warning] WSREP: Failed to apply app buffer: seqno: 982675, status: 1
         at galera/src/trx_handle.cpp:apply():351
Retrying 3th time
2017-04-07T10:51:14.879618Z 5 [ERROR] Slave SQL: Column 1 of table 'sbtest1.sbtest1' cannot be converted from type 'int' to type 'varchar(30)', Error_code: 1677
2017-04-07T10:51:14.879633Z 5 [Warning] WSREP: RBR event 3 Write_rows apply warning: 3, 982675
2017-04-07T10:51:14.879730Z 5 [Warning] WSREP: Failed to apply app buffer: seqno: 982675, status: 1
         at galera/src/trx_handle.cpp:apply():351
Retrying 4th time
2017-04-07T10:51:14.879911Z 5 [ERROR] Slave SQL: Column 1 of table 'sbtest1.sbtest1' cannot be converted from type 'int' to type 'varchar(30)', Error_code: 1677
2017-04-07T10:51:14.879924Z 5 [Warning] WSREP: RBR event 3 Write_rows apply warning: 3, 982675
2017-04-07T10:51:14.885255Z 5 [ERROR] WSREP: Failed to apply trx: source: 938415a6-1aab-11e7-ac29-0a69a4a1dafe version: 3 local: 0 state: APPLYING flags: 1 conn_id: 125559 trx_id: 2856843 seqnos (l: 392283, g: 9
82675, s: 982674, d: 982563, ts: 146831275805149)
2017-04-07T10:51:14.885271Z 5 [ERROR] WSREP: Failed to apply trx 982675 4 times
2017-04-07T10:51:14.885281Z 5 [ERROR] WSREP: Node consistency compromized, aborting…

जैसा कि देखा जा सकता है, गैलेरा ने इस तथ्य के बारे में शिकायत की कि कॉलम को INT से VARCHAR (30) में परिवर्तित नहीं किया जा सकता है। इसने चार बार राइटसेट को फिर से निष्पादित करने का प्रयास किया, लेकिन यह असफल रहा, आश्चर्यजनक रूप से। जैसे, गैलेरा ने निर्धारित किया कि नोड स्थिरता से समझौता किया गया है और नोड को क्लस्टर से बाहर निकाल दिया गया है। लॉग की शेष सामग्री इस प्रक्रिया को दर्शाती है:

2017-04-07T10:51:14.885560Z 5 [Note] WSREP: Closing send monitor...
2017-04-07T10:51:14.885630Z 5 [Note] WSREP: Closed send monitor.
2017-04-07T10:51:14.885644Z 5 [Note] WSREP: gcomm: terminating thread
2017-04-07T10:51:14.885828Z 5 [Note] WSREP: gcomm: joining thread
2017-04-07T10:51:14.885842Z 5 [Note] WSREP: gcomm: closing backend
2017-04-07T10:51:14.896654Z 5 [Note] WSREP: view(view_id(NON_PRIM,6fcd492a,37) memb {
        b13499a8,0
} joined {
} left {
} partitioned {
        6fcd492a,0
        938415a6,0
})
2017-04-07T10:51:14.896746Z 5 [Note] WSREP: view((empty))
2017-04-07T10:51:14.901477Z 5 [Note] WSREP: gcomm: closed
2017-04-07T10:51:14.901512Z 0 [Note] WSREP: New COMPONENT: primary = no, bootstrap = no, my_idx = 0, memb_num = 1
2017-04-07T10:51:14.901531Z 0 [Note] WSREP: Flow-control interval: [16, 16]
2017-04-07T10:51:14.901541Z 0 [Note] WSREP: Received NON-PRIMARY.
2017-04-07T10:51:14.901550Z 0 [Note] WSREP: Shifting SYNCED -> OPEN (TO: 982675)
2017-04-07T10:51:14.901563Z 0 [Note] WSREP: Received self-leave message.
2017-04-07T10:51:14.901573Z 0 [Note] WSREP: Flow-control interval: [0, 0]
2017-04-07T10:51:14.901581Z 0 [Note] WSREP: Received SELF-LEAVE. Closing connection.
2017-04-07T10:51:14.901589Z 0 [Note] WSREP: Shifting OPEN -> CLOSED (TO: 982675)
2017-04-07T10:51:14.901602Z 0 [Note] WSREP: RECV thread exiting 0: Success
2017-04-07T10:51:14.902701Z 5 [Note] WSREP: recv_thread() joined.
2017-04-07T10:51:14.902720Z 5 [Note] WSREP: Closing replication queue.
2017-04-07T10:51:14.902730Z 5 [Note] WSREP: Closing slave action queue.
2017-04-07T10:51:14.902742Z 5 [Note] WSREP: /usr/sbin/mysqld: Terminated.

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

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


  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 में RTRIM () फ़ंक्शन कैसे काम करता है

  2. मैं कोडइग्निटर में तैयार वक्तव्यों का उपयोग कैसे कर सकता हूं?

  3. ClusterControl के साथ HAProxy मेट्रिक्स की निगरानी कैसे करें

  4. प्रत्येक समूह से क्वेरी रिटर्न 1 पंक्ति चुनें

  5. MySQL डेटाबेस मैनेजमेंट सिस्टम (DBMS) के वर्तमान संस्करण को कैसे पुनः प्राप्त करें?