जब डेटा की सुरक्षा की बात आती है तो बैकअप महत्वपूर्ण होते हैं। वे अंतिम आपदा पुनर्प्राप्ति समाधान हैं - आपके पास कोई डेटाबेस नोड उपलब्ध नहीं है और आपका डेटासेंटर सचमुच धुएं में चला गया हो सकता है, लेकिन जब तक आपके पास अपने डेटा का बैकअप है, तब भी आप ऐसी स्थिति से उबर सकते हैं।
आमतौर पर, आप विभिन्न प्रकार के मामलों से उबरने के लिए बैकअप का उपयोग करेंगे:
- आकस्मिक ड्रॉप टेबल या WHERE क्लॉज के बिना DELETE, या WHERE क्लॉज के साथ जो पर्याप्त विशिष्ट नहीं था।
- डेटाबेस अपग्रेड जो विफल हो जाता है और डेटा को दूषित कर देता है
- संग्रहण मीडिया विफलता/भ्रष्टाचार
क्या बैकअप से पुनर्स्थापित करना पर्याप्त नहीं है? इसके लिए समय-समय पर क्या होना चाहिए? हमें यह ध्यान रखना होगा कि बैकअप एक निश्चित समय पर लिए गए डेटा का एक स्नैपशॉट है। यदि आप 1:00 बजे बैकअप लेते हैं और 11:00 बजे गलती से एक टेबल हटा दिया जाता है, तो आप 1:00 बजे तक अपना डेटा पुनर्स्थापित कर सकते हैं लेकिन उन परिवर्तनों का क्या जो सुबह 1:00 बजे से 11:00 बजे के बीच हुए हैं? वे परिवर्तन खो जाएंगे जब तक कि आप बीच में हुए संशोधनों को फिर से नहीं चला सकते। सौभाग्य से, MySQL में परिवर्तनों को संग्रहीत करने के लिए ऐसा तंत्र है - बाइनरी लॉग। आप जान सकते हैं कि वे लॉग प्रतिकृति के लिए उपयोग किए जाते हैं - MySQL उनका उपयोग उन सभी परिवर्तनों को संग्रहीत करने के लिए करता है जो मास्टर पर हुए थे, और एक दास उन परिवर्तनों को फिर से चलाने और उन्हें अपने डेटासेट पर लागू करने के लिए उनका उपयोग करता है। चूंकि बिनलॉग सभी परिवर्तनों को संग्रहीत करते हैं, आप उनका उपयोग ट्रैफ़िक को फिर से चलाने के लिए भी कर सकते हैं। इस ब्लॉग पोस्ट में, हम देखेंगे कि कैसे ClusterControl पॉइंट-इन-टाइम रिकवरी (PITR) करने में आपकी मदद कर सकता है।
प्वाइंट-इन-टाइम रिकवरी के साथ संगत बैकअप बनाना
सबसे पहले, पूर्वापेक्षाओं के बारे में बात करते हैं। जिस होस्ट से आप बैकअप लेते हैं उसके पास बाइनरी लॉग सक्षम होना चाहिए। उनके बिना पीआईटीआर संभव नहीं है। दूसरी आवश्यकता - एक मेजबान जहां से आप बैकअप लेते हैं, उसके पास एक निश्चित समय पर पुनर्स्थापित करने के लिए आवश्यक सभी बाइनरी लॉग होना चाहिए। यदि आप अत्यधिक आक्रामक बाइनरी लॉग रोटेशन का उपयोग करते हैं, तो यह एक समस्या बन सकती है।
तो, आइए देखें कि ClusterControl में इस सुविधा का उपयोग कैसे करें। सबसे पहले, आपको एक बैकअप लेना होगा जो PITR के अनुकूल हो। ऐसा बैकअप पूर्ण, पूर्ण और सुसंगत होना चाहिए। एक्स्ट्राबैकअप के लिए, जब तक इसमें पूर्ण डेटासेट होता है (आपने केवल स्कीमा का एक सबसेट शामिल नहीं किया है), यह PITR-संगत होगा।
Mysqldump के लिए, इसे PITR-संगत बनाने का एक विकल्प है। जब आप इस विकल्प को सक्षम करते हैं, तो सभी आवश्यक विकल्प कॉन्फ़िगर किए जाएंगे (उदाहरण के लिए, आप डंप में शामिल करने के लिए अलग स्कीमा नहीं चुन पाएंगे) और बैकअप को पॉइंट-इन-टाइम पुनर्प्राप्ति के लिए उपलब्ध के रूप में चिह्नित किया जाएगा।
बैकअप से पॉइंट-इन-टाइम रिकवरी
सबसे पहले, आपको पुनर्स्थापित करने के लिए एक बैकअप चुनना होगा।
यदि बैकअप PITR के साथ संगत है, तो पॉइंट-इन-टाइम रिकवरी करने के लिए एक विकल्प प्रस्तुत किया जाएगा। उसके लिए आपके पास दो विकल्प होंगे - "समय आधारित" और "स्थिति आधारित"। आइए उन दो विकल्पों के बीच के अंतर पर चर्चा करें।
“समय आधारित” PITR
इस विकल्प के साथ आप एक तिथि और समय पास कर सकते हैं, जिसके लिए बैकअप को पुनर्स्थापित किया जाना चाहिए। इसे एक सेकंड के संकल्प के भीतर परिभाषित किया जा सकता है। यह गारंटी नहीं देता है कि सभी डेटा को पुनर्स्थापित किया जाएगा, क्योंकि भले ही आप समय को परिभाषित करने में बहुत सटीक हों, एक सेकंड के दौरान कई घटनाओं को बाइनरी लॉग में रिकॉर्ड किया जा सकता है। बता दें कि डेटा लॉस 18 अप्रैल को 10:00:01 बजे हुआ था। आप फॉर्म में निम्नलिखित तिथि और समय पास करते हैं:'2018-04-18 10:00:00'। कृपया ध्यान रखें कि आपको ऐसे समय का उपयोग करना चाहिए जो उस डेटाबेस सर्वर पर समय क्षेत्र सेटिंग्स पर आधारित हो जिस पर बैकअप बनाया गया था।
यह अभी भी हो सकता है कि डेटा हानि पहली बार नहीं हुई थी जो 10:00:01 पर हुई थी, इसलिए इस प्रक्रिया में कुछ घटनाएं खो जाएंगी। आइए देखें कि इसका क्या अर्थ है।
एक सेकंड के दौरान, बिनलॉग में कई इवेंट लॉग किए जा सकते हैं। आइए ऐसे मामले पर विचार करें:
10:00:00 - ईवेंट A,B,C,D,E,F
10:00:01 - ईवेंट V,W,X,Y,Z
जहां एक्स डेटा हानि घटना है। एक सेकंड की ग्रैन्युलैरिटी के साथ, आप या तो 10:00:00 (इसलिए F तक) या 10:00:01 (Z तक) तक हुई हर चीज को पुनर्स्थापित कर सकते हैं। बाद का मामला किसी काम का नहीं है क्योंकि एक्स को फिर से निष्पादित किया जाएगा। पहले वाले मामले में, हम V और W को याद करते हैं।
इसलिए स्थिति आधारित पुनर्स्थापना अधिक सटीक है। आप कह सकते हैं "मैं डब्ल्यू तक पुनर्स्थापित करना चाहता हूं"।
समय आधारित पुनर्स्थापना सबसे सटीक है जिसे आप बाइनरी लॉग में जाने के बिना प्राप्त कर सकते हैं और सटीक स्थिति को परिभाषित कर सकते हैं जहां आप पुनर्स्थापित करना चाहते हैं। यह हमें PITR करने की दूसरी विधि की ओर ले जाता है।
“स्थिति आधारित” PITR
यहां MySQL के लिए कमांड लाइन टूल्स के साथ कुछ अनुभव, अर्थात् mysqlbinlog उपयोगिता की आवश्यकता है। दूसरी ओर, पुनर्प्राप्ति कैसे की जाएगी, इस पर आपका सबसे अच्छा नियंत्रण होगा।
आइए एक सरल उदाहरण के माध्यम से चलते हैं। जैसा कि आप ऊपर स्क्रीनशॉट में देख सकते हैं, आपको एक बाइनरी लॉग नाम और बाइनरी लॉग स्थिति पास करनी होगी, जिस बिंदु तक बैकअप को पुनर्स्थापित किया जाना चाहिए। अधिकांश समय, डेटा हानि घटना से पहले यह अंतिम स्थिति होनी चाहिए।
किसी ने SQL कमांड निष्पादित किया जिसके परिणामस्वरूप गंभीर डेटा हानि हुई:
mysql> DROP TABLE sbtest1;
Query OK, 0 rows affected (0.02 sec)
हमारे आवेदन ने तुरंत शिकायत करना शुरू कर दिया:
sysbench 1.1.0-ecf1191 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 2
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
FATAL: mysql_drv_query() returned error 1146 (Table 'sbtest.sbtest1' doesn't exist) for query 'DELETE FROM sbtest1 WHERE id=5038'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:490: SQL error, errno = 1146, state = '42S02': Table 'sbtest.sbtest1' doesn't exist
हमारे पास एक बैकअप है लेकिन हम उस घातक क्षण तक के सभी डेटा को पुनर्स्थापित करना चाहते हैं। सबसे पहले, हम मानते हैं कि एप्लिकेशन काम नहीं करता है, इसलिए हम ड्रॉप टेबल के बाद हुए सभी लेखन को गैर-महत्वपूर्ण के रूप में छोड़ सकते हैं। यदि आपका आवेदन कुछ हद तक काम करता है, तो आपको शेष परिवर्तनों को बाद में मर्ज करना होगा। ठीक है, आइए DROP TABLE स्टेटमेंट की स्थिति का पता लगाने के लिए बाइनरी लॉग की जांच करें। जैसा कि हम सभी बाइनरी लॉग को पार्स करने से बचना चाहते हैं, आइए जानें कि हमारा नवीनतम बैकअप किस स्थिति में था। आप नवीनतम बैकअप सेट के लिए लॉग की जांच करके इसकी जांच कर सकते हैं और इसके समान एक लाइन ढूंढ सकते हैं:
तो, हम फ़ाइल नाम 'binlog.000008' और स्थिति '16184120' के बारे में बात कर रहे हैं। आइए इसे अपने शुरुआती बिंदु के रूप में उपयोग करें। आइए देखें कि हमारे पास कौन सी बाइनरी लॉग फ़ाइलें हैं:
[email protected]:~# ls -alh /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql 58M Apr 17 08:31 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql 116M Apr 17 08:59 /var/lib/mysql/binlog.000002
-rw-r----- 1 mysql mysql 379M Apr 17 09:30 /var/lib/mysql/binlog.000003
-rw-r----- 1 mysql mysql 344M Apr 17 10:54 /var/lib/mysql/binlog.000004
-rw-r----- 1 mysql mysql 892K Apr 17 10:56 /var/lib/mysql/binlog.000005
-rw-r----- 1 mysql mysql 74M Apr 17 11:03 /var/lib/mysql/binlog.000006
-rw-r----- 1 mysql mysql 5.2M Apr 17 11:06 /var/lib/mysql/binlog.000007
-rw-r----- 1 mysql mysql 21M Apr 18 11:35 /var/lib/mysql/binlog.000008
-rw-r----- 1 mysql mysql 59K Apr 18 11:35 /var/lib/mysql/binlog.000009
-rw-r----- 1 mysql mysql 144 Apr 18 11:35 /var/lib/mysql/binlog.index
इसलिए, 'binlog.000008' के अलावा हमारे पास जांच करने के लिए 'binlog.000009' भी है। आइए कमांड चलाते हैं जो बाइनरी लॉग को SQL फॉर्मेट में बदल देगा, जो हमें बैकअप लॉग में मिली स्थिति से शुरू होता है:
[email protected]:~# mysqlbinlog --start-position='16184120' --verbose /var/lib/mysql/binlog.000008 /var/lib/mysql/binlog.000009 > binlog.out
पंक्ति-आधारित घटनाओं को डीकोड करने के लिए कृपया नोड '--verbose' आवश्यक है। हम जिस ड्रॉप टेबल की तलाश कर रहे हैं, उसके लिए यह आवश्यक नहीं है, लेकिन अन्य प्रकार के आयोजनों के लिए इसकी आवश्यकता हो सकती है।
आइए DROP TABLE क्वेरी के लिए अपना आउटपुट खोजें:
[email protected]:~# grep -B 7 -A 1 "DROP TABLE" binlog.out
# at 20885489
#180418 11:24:32 server id 1 end_log_pos 20885554 CRC32 0xb89f2e66 GTID last_committed=38168 sequence_number=38170 rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
# at 20885554
#180418 11:24:32 server id 1 end_log_pos 20885678 CRC32 0xb38a427b Query thread_id=54 exec_time=0 error_code=0
use `sbtest`/*!*/;
SET TIMESTAMP=1524050672/*!*/;
DROP TABLE `sbtest1` /* generated by server */
/*!*/;
इस नमूने में हम दो घटनाएँ देख सकते हैं। सबसे पहले, 20885489 की स्थिति पर, GTID_NEXT चर सेट करता है।
# at 20885489
#180418 11:24:32 server id 1 end_log_pos 20885554 CRC32 0xb89f2e66 GTID last_committed=38168 sequence_number=38170 rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
दूसरा, 20885554 की स्थिति में हमारा ड्रॉप टेबल इवेंट है। इससे यह निष्कर्ष निकलता है कि हमें 20885489 की स्थिति तक पीआईटीआर का प्रदर्शन करना चाहिए। उत्तर देने के लिए एकमात्र प्रश्न यह है कि हम किस बाइनरी लॉग के बारे में बात कर रहे हैं। हम बिनलॉग रोटेशन प्रविष्टियों की खोज करके इसकी जांच कर सकते हैं:
[email protected]:~# grep "Rotate to binlog" binlog.out
#180418 11:35:46 server id 1 end_log_pos 21013114 CRC32 0x2772cc18 Rotate to binlog.000009 pos: 4
जैसा कि तिथियों की तुलना करके स्पष्ट रूप से देखा जा सकता है, binlog.000009 पर रोटेशन बाद में हुआ इसलिए हम binlog.000008 को फॉर्म में binlog फ़ाइल के रूप में पास करना चाहते हैं।
अगला, हमें यह तय करना होगा कि क्या हम क्लस्टर पर बैकअप को पुनर्स्थापित करने जा रहे हैं या क्या हम इसे पुनर्स्थापित करने के लिए बाहरी सर्वर का उपयोग करना चाहते हैं। यदि आप डेटा के केवल एक सबसेट को पुनर्स्थापित करना चाहते हैं तो यह दूसरा विकल्प उपयोगी हो सकता है। आप एक अलग होस्ट पर पूर्ण भौतिक बैकअप को पुनर्स्थापित कर सकते हैं और फिर लापता डेटा को डंप करने और इसे उत्पादन सर्वर पर लोड करने के लिए mysqldump का उपयोग कर सकते हैं।
ध्यान रखें कि जब आप अपने क्लस्टर पर बैकअप को पुनर्स्थापित करते हैं, तो आपको अपने द्वारा पुनर्प्राप्त किए गए नोड के अलावा अन्य नोड्स का पुनर्निर्माण करना होगा। मास्टर-स्लेव परिदृश्य में आप आमतौर पर मास्टर पर बैकअप को पुनर्स्थापित करना चाहते हैं और फिर इससे दासों को फिर से बनाना चाहते हैं।
अंतिम चरण के रूप में, आपको ClusterControl द्वारा की जाने वाली कार्रवाइयों का सारांश दिखाई देगा।
अंत में, बैकअप बहाल होने के बाद, हम परीक्षण करेंगे कि लापता तालिका को पुनर्स्थापित किया गया है या नहीं:
mysql> show tables from sbtest like 'sbtest1'\G
*************************** 1. row ***************************
Tables_in_sbtest (sbtest1): sbtest1
1 row in set (0.00 sec)
सब कुछ ठीक लगता है, हम लापता डेटा को पुनर्स्थापित करने में कामयाब रहे।
आखिरी कदम जो हमें उठाना है वह है अपने दास का पुनर्निर्माण करना। कृपया ध्यान दें कि PITR बैकअप का उपयोग करने का एक विकल्प है। यहाँ उदाहरण में, यह संभव नहीं है क्योंकि दास DROP TABLE घटना को दोहराएगा और अंत में यह मास्टर के अनुरूप नहीं होगा।