मारियाडीबी ने फ्लैशबैक नामक एक बहुत ही शानदार फीचर पेश किया है। फ्लैशबैक एक ऐसी सुविधा है जो इंस्टेंस, डेटाबेस या टेबल को पुराने स्नैपशॉट में वापस ले जाने की अनुमति देगी। परंपरागत रूप से, पॉइंट-इन-टाइम रिकवरी (PITR) करने के लिए, एक बैकअप से एक डेटाबेस को पुनर्स्थापित करेगा, और एक निश्चित समय या स्थिति में डेटाबेस स्थिति को आगे बढ़ाने के लिए बाइनरी लॉग को फिर से चलाएगा।
फ्लैशबैक के साथ, डेटाबेस को अतीत में एक बिंदु पर वापस लाया जा सकता है, जो कि बहुत तेज़ है यदि हम केवल उस अतीत को देखना चाहते हैं जो अभी बहुत समय पहले नहीं हुआ था। कभी-कभी, यदि आप वर्तमान दिनांक और समय के सापेक्ष अपने डेटा का एक बहुत पुराना स्नैपशॉट देखना चाहते हैं, तो फ्लैशबैक का उपयोग करना अक्षम हो सकता है। विलंबित दास से पुनर्स्थापित करना, या बैकअप से बाइनरी लॉग को फिर से चलाना बेहतर विकल्प हो सकता है।
यह सुविधा केवल मारियाडीबी क्लाइंट पैकेज में उपलब्ध है, लेकिन इसका मतलब यह नहीं है कि हम इसे अपने MySQL सर्वर के साथ उपयोग नहीं कर सकते हैं। यह ब्लॉग पोस्ट दिखाता है कि कैसे हम एक MySQL सर्वर पर इस अद्भुत सुविधा का उपयोग कर सकते हैं।
MariaDB फ्लैशबैक आवश्यकताएँ
उन लोगों के लिए जो MySQL के शीर्ष पर मारियाडीबी फ्लैशबैक सुविधा का उपयोग करना चाहते हैं, हम मूल रूप से निम्न कार्य कर सकते हैं:
- निम्न सेटिंग के साथ बाइनरी लॉग सक्षम करें:
- binlog_format =ROW (MySQL 5.7.7 के बाद से डिफ़ॉल्ट)।
- binlog_row_image =पूर्ण (MySQL 5.6 के बाद से डिफ़ॉल्ट)।
- किसी भी MariaDB 10.2.4 और बाद के इंस्टॉलेशन से msqlbinlog उपयोगिता का उपयोग करें।
- फ्लैशबैक वर्तमान में केवल DML स्टेटमेंट्स (INSERT, DELETE, UPDATE) पर समर्थित है। मारियाडीबी का एक आगामी संस्करण डीडीएल स्टेटमेंट्स (DROP, TRUNCATE, ALTER, आदि) पर फ्लैशबैक के लिए समर्थन जोड़ देगा, वर्तमान तालिका को एक आरक्षित और छिपे हुए डेटाबेस में कॉपी या स्थानांतरित करके, और फिर फ्लैशबैक का उपयोग करते समय कॉपी या वापस ले जाएगा।
पूर्ण छवि प्रारूप बाइनरी लॉग के लिए मौजूदा समर्थन का लाभ उठाकर फ्लैशबैक प्राप्त किया जाता है, इस प्रकार यह सभी स्टोरेज इंजनों का समर्थन करता है। ध्यान दें कि फ्लैशबैक इवेंट्स को मेमोरी में स्टोर किया जाएगा। इसलिए, आपको यह सुनिश्चित करना चाहिए कि आपके सर्वर में इस सुविधा के लिए पर्याप्त मेमोरी है।
मारियाडीबी फ्लैशबैक कैसे काम करता है?
MariaDB की mysqlbinlog उपयोगिता इस उद्देश्य के लिए दो अतिरिक्त विकल्पों के साथ आती है:
- -B, --flashback - Flashback सुविधा आपके प्रतिबद्ध डेटा को एक विशेष समय बिंदु पर रोलबैक कर सकती है।
- -T, --table=[name] - इस तालिका के लिए सूची प्रविष्टियां (केवल स्थानीय लॉग)।
--flashback ध्वज के साथ और उसके बिना mysqlbinlog आउटपुट की तुलना करके, हम आसानी से समझ सकते हैं कि यह कैसे काम करता है। मारियाडीबी सर्वर पर निम्नलिखित कथन को निष्पादित करने पर विचार करें:
MariaDB> DELETE FROM sbtest.sbtest1 WHERE id = 1;
फ्लैशबैक फ़्लैग के बिना, हम वास्तविक DELETE बिनलॉग ईवेंट देखेंगे:
$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 10 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000003
...
# at 453196541
#200227 12:58:18 server id 37001 end_log_pos 453196766 CRC32 0xdaa248ed Delete_rows: table id 238 flags: STMT_END_F
BINLOG '
6rxXXhOJkAAAQwAAAP06AxsAAO4AAAAAAAEABnNidGVzdAAHc2J0ZXN0MQAEAwP+/gTu4P7wAAEB
AAID/P8AFuAQfA==
6rxXXiCJkAAA4QAAAN47AxsAAO4AAAAAAAEAAgAE/wABAAAAVJ4HAHcAODM4Njg2NDE5MTItMjg3
NzM5NzI4MzctNjA3MzYxMjA0ODYtNzUxNjI2NTk5MDYtMjc1NjM1MjY0OTQtMjAzODE4ODc0MDQt
NDE1NzY0MjIyNDEtOTM0MjY3OTM5NjQtNTY0MDUwNjUxMDItMzM1MTg0MzIzMzA7Njc4NDc5Njcz
NzctNDgwMDA5NjMzMjItNjI2MDQ3ODUzMDEtOTE0MTU0OTE4OTgtOTY5MjY1MjAyOTHtSKLa
'/*!*/;
### DELETE FROM `sbtest`.`sbtest1`
### WHERE
### @1=1 /* INT meta=0 nullable=0 is_null=0 */
### @2=499284 /* INT meta=0 nullable=0 is_null=0 */
### @3='83868641912-28773972837-60736120486-75162659906-27563526494-20381887404-41576422241-93426793964-56405065102-33518432330' /* STRING(480) meta=61152 nullable=0 is_null=0 */
### @4='67847967377-48000963322-62604785301-91415491898-96926520291' /* STRING(240) meta=65264 nullable=0 is_null=0 */
...
उपरोक्त mysqlbinlog कमांड को --flashback के साथ विस्तारित करके, हम देख सकते हैं कि DELETE ईवेंट INSERT ईवेंट में परिवर्तित हो गया है और इसी तरह संबंधित WHERE और SET क्लॉज़ में:
$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 10 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000003 \
--flashback
...
BINLOG '
6rxXXhOJkAAAQwAAAP06AxsAAO4AAAAAAAEABnNidGVzdAAHc2J0ZXN0MQAEAwP+/gTu4P7wAAEB
AAID/P8AFuAQfA==
6rxXXh6JkAAA4QAAAN47AxsAAO4AAAAAAAEAAgAE/wABAAAAVJ4HAHcAODM4Njg2NDE5MTItMjg3
NzM5NzI4MzctNjA3MzYxMjA0ODYtNzUxNjI2NTk5MDYtMjc1NjM1MjY0OTQtMjAzODE4ODc0MDQt
NDE1NzY0MjIyNDEtOTM0MjY3OTM5NjQtNTY0MDUwNjUxMDItMzM1MTg0MzIzMzA7Njc4NDc5Njcz
NzctNDgwMDA5NjMzMjItNjI2MDQ3ODUzMDEtOTE0MTU0OTE4OTgtOTY5MjY1MjAyOTHtSKLa
'/*!*/;
### INSERT INTO `sbtest`.`sbtest1`
### SET
### @1=1 /* INT meta=0 nullable=0 is_null=0 */
### @2=499284 /* INT meta=0 nullable=0 is_null=0 */
### @3='83868641912-28773972837-60736120486-75162659906-27563526494-20381887404-41576422241-93426793964-56405065102-33518432330' /* STRING(480) meta=61152 nullable=0 is_null=0 */
### @4='67847967377-48000963322-62604785301-91415491898-96926520291' /* STRING(240) meta=65264 nullable=0 is_null=0 */
...
पंक्ति-आधारित प्रतिकृति (binlog_format=ROW) में, प्रत्येक पंक्ति परिवर्तन घटना में दो छवियां होती हैं, एक "पहले" छवि (INSERT को छोड़कर) जिनके कॉलम को अद्यतन करने के लिए पंक्ति की खोज करते समय मिलान किया जाता है, और एक "बाद" छवि (DELETE को छोड़कर) जिसमें परिवर्तन शामिल हैं। binlog_row_image=FULL के साथ, MariaDB पहले और बाद की छवियों के लिए पूरी पंक्तियों (यानी, सभी कॉलम) को लॉग करता है।
निम्न उदाहरण अद्यतन के लिए बाइनरी लॉग इवेंट दिखाता है। मारियाडीबी सर्वर पर निम्नलिखित कथन को निष्पादित करने पर विचार करें:
MariaDB> UPDATE sbtest.sbtest1 SET k = 0 WHERE id = 5;
उपरोक्त कथन के लिए बिनलॉग इवेंट को देखते समय, हम कुछ इस तरह देखेंगे:
$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 5 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000001
...
### UPDATE `sbtest`.`sbtest1`
### WHERE
### @1=5 /* INT meta=0 nullable=0 is_null=0 */
### @2=499813 /* INT meta=0 nullable=0 is_null=0 */
### @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
### @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
### SET
### @1=5 /* INT meta=0 nullable=0 is_null=0 */
### @2=0 /* INT meta=0 nullable=0 is_null=0 */
### @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
### @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
# Number of rows: 1
...
--flashback ध्वज के साथ, "पहले" छवि को मौजूदा पंक्ति की "बाद" छवि के साथ बदल दिया जाता है:
$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 5 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000001 \
--flashback
...
### UPDATE `sbtest`.`sbtest1`
### WHERE
### @1=5 /* INT meta=0 nullable=0 is_null=0 */
### @2=0 /* INT meta=0 nullable=0 is_null=0 */
### @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
### @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
### SET
### @1=5 /* INT meta=0 nullable=0 is_null=0 */
### @2=499813 /* INT meta=0 nullable=0 is_null=0 */
### @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
### @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
...
फिर हम फ्लैशबैक आउटपुट को MySQL क्लाइंट पर रीडायरेक्ट कर सकते हैं, इस प्रकार डेटाबेस या टेबल को उस समय तक वापस ले जा सकते हैं जो हम चाहते हैं। अगले अनुभागों में और उदाहरण दिखाए गए हैं।
इस सुविधा के लिए मारियाडीबी के पास एक समर्पित ज्ञानकोष पृष्ठ है। मारियाडीबी फ्लैशबैक नॉलेज बेस पेज देखें।
MySQL के साथ मारियाडीबी फ्लैशबैक
MySQL के लिए फ्लैशबैक क्षमता प्राप्त करने के लिए, किसी को निम्न कार्य करने होंगे:
- mysqlbinlog उपयोगिता को किसी भी MariaDB सर्वर (10.2.4 या बाद के संस्करण) से कॉपी करें।
- फ़्लैशबैक SQL फ़ाइल लागू करने से पहले MySQL GTID अक्षम करें। MySQL 5.7.5 के बाद से वैश्विक चर gtid_mode और Enforce_gtid_consistency को रनटाइम में सेट किया जा सकता है।
मान लीजिए कि हमारे पास निम्नलिखित सरल MySQL 8.0 प्रतिकृति टोपोलॉजी है:
इस उदाहरण में, हमने अपने MySQL 8.0 स्लेव (दास 2) में से एक पर नवीनतम मारियाडीबी 10.4 से mysqlbinlog उपयोगिता की प्रतिलिपि बनाई:
(mariadb-server)$ scp /bin/mysqlbinlog [email protected]:/root/
(slave2-mysql8)$ ls -l /root/mysqlbinlog
-rwxr-xr-x. 1 root root 4259504 Feb 27 13:44 /root/mysqlbinlog
हमारी मारियाडीबी की mysqlbinlog उपयोगिता अब स्लेव2 पर /root/mysqlbinlog पर स्थित है। MySQL मास्टर पर, हमने निम्नलिखित विनाशकारी कथन निष्पादित किए:
mysql> DELETE FROM sbtest1 WHERE id BETWEEN 5 AND 100;
Query OK, 96 rows affected (0.01 sec)
उपरोक्त कथन में 96 पंक्तियों को हटा दिया गया था। इससे पहले कि हम दास सर्वर पर विनाशकारी घटना की बिनलॉग स्थिति खोजने का प्रयास कर सकें, घटनाओं को मास्टर से सभी दासों तक दोहराने के लिए कुछ सेकंड प्रतीक्षा करें। पहला कदम उस सर्वर पर सभी बाइनरी लॉग को पुनः प्राप्त करना है:
mysql> SHOW BINARY LOGS;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 850 | No |
| binlog.000002 | 18796 | No |
+---------------+-----------+-----------+
हमारी विनाशकारी घटना इस सर्वर में नवीनतम बाइनरी लॉग binlog.000002 के अंदर मौजूद होनी चाहिए। फिर हम 10 मिनट पहले से तालिका sbtest1 के लिए सभी बिनलॉग ईवेंट पुनर्प्राप्त करने के लिए MariaDB की mysqlbinlog उपयोगिता का उपयोग कर सकते हैं:
(slave2-mysql8)$ /root/mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 10 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000002
...
# at 195
#200228 15:09:45 server id 37001 end_log_pos 281 CRC32 0x99547474 Ignorable
# Ignorable event type 33 (MySQL Gtid)
# at 281
#200228 15:09:45 server id 37001 end_log_pos 353 CRC32 0x8b12bd3c Query thread_id=19 exec_time=0 error_code=0
SET TIMESTAMP=1582902585/*!*/;
SET @@session.pseudo_thread_id=19/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/;
SET @@session.sql_mode=524288/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 353
#200228 15:09:45 server id 37001 end_log_pos 420 CRC32 0xe0e44a1b Table_map: `sbtest`.`sbtest1` mapped to number 92
# at 420
# at 8625
# at 16830
#200228 15:09:45 server id 37001 end_log_pos 8625 CRC32 0x99b1a8fc Delete_rows: table id 92
#200228 15:09:45 server id 37001 end_log_pos 16830 CRC32 0x89496a07 Delete_rows: table id 92
#200228 15:09:45 server id 37001 end_log_pos 18765 CRC32 0x302413b2 Delete_rows: table id 92 flags: STMT_END_F
बिनलॉग स्थिति संख्या को आसानी से देखने के लिए, "# at" से शुरू होने वाली पंक्तियों पर ध्यान दें। उपरोक्त पंक्तियों से, हम देख सकते हैं कि DELETE घटना binlog.000002 के अंदर 281 की स्थिति में हो रही थी ("# 281 पर शुरू होती है")। हम सीधे एक MySQL सर्वर के अंदर बिनलॉग ईवेंट को पुनः प्राप्त कर सकते हैं:
mysql> SHOW BINLOG EVENTS IN 'binlog.000002';
+---------------+-------+----------------+-----------+-------------+-------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+-------+----------------+-----------+-------------+-------------------------------------------------------------------+
| binlog.000002 | 4 | Format_desc | 37003 | 124 | Server ver: 8.0.19, Binlog ver: 4 |
| binlog.000002 | 124 | Previous_gtids | 37003 | 195 | 0d98d975-59f8-11ea-bd30-525400261060:1 |
| binlog.000002 | 195 | Gtid | 37001 | 281 | SET @@SESSION.GTID_NEXT= '0d98d975-59f8-11ea-bd30-525400261060:2' |
| binlog.000002 | 281 | Query | 37001 | 353 | BEGIN |
| binlog.000002 | 353 | Table_map | 37001 | 420 | table_id: 92 (sbtest.sbtest1) |
| binlog.000002 | 420 | Delete_rows | 37001 | 8625 | table_id: 92 |
| binlog.000002 | 8625 | Delete_rows | 37001 | 16830 | table_id: 92 |
| binlog.000002 | 16830 | Delete_rows | 37001 | 18765 | table_id: 92 flags: STMT_END_F |
| binlog.000002 | 18765 | Xid | 37001 | 18796 | COMMIT /* xid=171006 */ |
+---------------+-------+----------------+-----------+-------------+-------------------------------------------------------------------+
9 rows in set (0.00 sec)
अब हम पुष्टि कर सकते हैं कि स्थिति 281 वह जगह है जहां हम अपने डेटा को वापस लाना चाहते हैं। फिर हम सटीक फ़्लैश बैक ईवेंट उत्पन्न करने के लिए --स्टार्ट-पोज़िशन फ़्लैग का उपयोग कर सकते हैं। ध्यान दें कि हम "-vv" ध्वज को छोड़ देते हैं और --फ़्लैशबैक फ़्लैग जोड़ें:
(slave2-mysql8)$ /root/mysqlbinlog \
--start-position=281 \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000002 \
--flashback > /root/flashback.binlog
Flashback.binlog में इस MySQL सर्वर पर तालिका sbtest1 पर हुए सभी परिवर्तनों को पूर्ववत करने के लिए सभी आवश्यक ईवेंट शामिल हैं। चूंकि यह एक प्रतिकृति क्लस्टर का एक दास नोड है, इसलिए हमें इसे फ्लैशबैक उद्देश्यों के लिए उपयोग करने के लिए चुने हुए दास (दास 2) पर प्रतिकृति को तोड़ना होगा। ऐसा करने के लिए, हमें चुने हुए दास पर प्रतिकृति को रोकना होगा, MySQL GTID को ON_PERMISSIVE पर सेट करना होगा और दास को लिखने योग्य बनाना होगा:
mysql> STOP SLAVE;
SET GLOBAL gtid_mode = ON_PERMISSIVE;
SET GLOBAL enforce_gtid_consistency = OFF;
SET GLOBAL read_only = OFF;
इस समय, स्लेव2 प्रतिकृति का हिस्सा नहीं है और हमारी टोपोलॉजी इस तरह दिख रही है:
mysql क्लाइंट के माध्यम से फ्लैशबैक आयात करें और हम नहीं चाहते कि यह परिवर्तन हो MySQL बाइनरी लॉग में रिकॉर्ड किया गया:
(slave2-mysql8)$ mysql -uroot -p --init-command='SET sql_log_bin=0' sbtest < /root/flashback.binlog
तब हम सभी हटाई गई पंक्तियों को देख सकते हैं, जैसा कि निम्नलिखित कथन से सिद्ध होता है:
mysql> SELECT COUNT(id) FROM sbtest1 WHERE id BETWEEN 5 and 100;
+-----------+
| COUNT(id) |
+-----------+
| 96 |
+-----------+
1 row in set (0.00 sec)
फिर हम अपने संदर्भ के लिए तालिका sbtest1 के लिए SQL डंप फ़ाइल बना सकते हैं:
(slave2-mysql8)$ mysqldump -uroot -p --single-transaction sbtest sbtest1 > sbtest1_flashbacked.sql
फ्लैशबैक ऑपरेशन पूरा होने के बाद, हम दास नोड को प्रतिकृति श्रृंखला में वापस जोड़ सकते हैं। लेकिन सबसे पहले, हमें उस स्थिति से शुरू होने वाली सभी घटनाओं को फिर से चलाकर डेटाबेस को एक सुसंगत स्थिति में वापस लाना होगा, जिसे हमने फ्लैशबैक किया था। बाइनरी लॉगिंग को छोड़ना न भूलें क्योंकि हम दास पर "लिखना" नहीं चाहते हैं और गलत लेनदेन के साथ खुद को जोखिम में डाल रहे हैं:
(slave2-mysql8)$ /root/mysqlbinlog \
--start-position=281 \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000002 | mysql -uroot -p --init-command='SET sql_log_bin=0' sbtest
अंत में, नोड को MySQL स्लेव के रूप में अपनी भूमिका के लिए वापस तैयार करें और प्रतिकृति शुरू करें:
mysql> SET GLOBAL read_only = ON;
SET GLOBAL enforce_gtid_consistency = ON;
SET GLOBAL gtid_mode = ON;
START SLAVE;
सत्यापित करें कि स्लेव नोड सही ढंग से नकल कर रहा है:
mysql> SHOW SLAVE STATUS\G
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
इस बिंदु पर, हम दास को प्रतिकृति श्रृंखला में फिर से शामिल कर चुके हैं और हमारी टोपोलॉजी अब अपनी मूल स्थिति में वापस आ गई है:
इस आश्चर्यजनक सुविधा को शुरू करने के लिए मारियाडीबी टीम को धन्यवाद!