गलती से उत्पादन आधार हटा दिया गया? आगे क्या है?

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


पर्यावरण का परीक्षण करें


CentOS 5.6 x86_64 और mysql 5.0.77 के साथ एक आभासी मशीन हाथ में आ गई
एक परीक्षण डेटाबेस MyISAM और InnoDB दोनों की एक जोड़ी तालिकाओं के साथ बनाया गया था। और उनकी वसूली की जाँच करने के लिए संग्रहीत प्रक्रियाओं के एक जोड़े:
DROP DATABASE prod;
CREATE DATABASE prod;
USE prod;
CREATE TABLE table1 (
id INTEGER ,
v VARCHAR (50),
PRIMARY KEY (id)
) ENGINE=MyISAM;

CREATE TABLE table2 (
id INTEGER ,
v VARCHAR (50),
PRIMARY KEY (id)
) ENGINE=InnoDB;

DELIMITER //

CREATE PROCEDURE dorepeat(p1 INT )
BEGIN
SET @x = 0;
REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
END
//

DELIMITER ;

CREATE FUNCTION hello (s CHAR (20))
RETURNS CHAR (50) DETERMINISTIC
RETURN CONCAT( 'Hello, ' ,s, '!' );


* This source code was highlighted with Source Code Highlighter .

खैर, वहाँ कुछ डेटा बनाएँ:
 ( for i in $(seq 1 100); do echo "insert into table1 values ($i, '`md5sum <<< "$i"`');"; done; ) >> test.sql ( for i in $(seq 1 100); do echo "insert into table2 values ($i, '`md5sum <<< "$i"`');"; done; ) >> test.sql 

पुनर्प्राप्ति की मौलिक संभावना पर विचार करने के लिए परीक्षण परिदृश्य को बहुत सरल चुना गया है।

प्यारे जानवर अपूर्ण रूप से क्रेप करते हैं


हम सभी ने डेटाबेस को बनाया और सत्यापित किया है कि डेटाबेस जिम्मेदार है और इसमें कुछ जानकारी है:
 mysql> select count(*) from table1; +----------+ | count(*) | +----------+ | 100 | +----------+ 1 row in set (0.00 sec) mysql> select count(*) from table2; +----------+ | count(*) | +----------+ | 100 | +----------+ 1 row in set (0.00 sec) mysql> select hello('world'); +----------------+ | hello('world') | +----------------+ | Hello, world! | +----------------+ 1 row in set (0.00 sec) 

एक साधारण आदेश के साथ एक आधार हटाने के साथ एक सफाई महिला का अनुकरण करें:
 # rm -rf / var / lib / mysql / * 

लेख से सलाह के अनुसार, हम सर्वर को पुनरारंभ नहीं करते हैं और mysql को रोकते नहीं हैं ताकि फ़ाइल डिस्क्रिप्टर खुले रहें (अन्यथा जानकारी खो जाएगी और एफएस में प्रत्यक्ष हस्तक्षेप बहाल करने के लिए आवश्यक हो सकता है)।
आप तुरंत सत्यापित कर सकते हैं कि ऊपर वर्णित एक कम से कम काम नहीं करता है क्योंकि सॉकेट को हटा दिया गया है:
 # mysql
 ERROR 2002 (HY000): सॉकेट '/var/lib/mysql/mysql.sock' (2) के माध्यम से स्थानीय MySQL सर्वर से कनेक्ट नहीं हो सकता

यदि आप tcp के माध्यम से जुड़ने की कोशिश करते हैं, तो हम अभी भी निराश होंगे, क्योंकि mysql पहले से ही डेटाबेस के बारे में कुछ नहीं जानता है और mysqldump एक खाली आउटपुट देगा:
 # mysql --protocol tcp <<< "शो डेटाबेस;"
 डाटाबेस
 INFORMATION_SCHEMA
 # mysqldump --protocol tcp -A
 - MySQL डंप 10.11
 -
 - होस्ट: लोकलहोस्ट डेटाबेस: 
 - ------------------------------------------------ ------
 - सर्वर संस्करण 5.0.77

 / *; 40101 SET @OLD_CHARACTER_SET_CLIENT = @@ CHARACTER_SET_CLIENT * /;
 / *; 40101 SET @OLD_CHARACTER_SET_RESULTS = @@ CHARACTER_SET_RESULTS * /;
 / *! 40101 SET @OLD_COLLATION_CONNECTION = @@ COLLATION_CONNECTION * /;
 / *; ४०१०१ सेट नेम्स utf8 * /;
 / *! 40103 SET @OLD_TIME_ZONE = @@ TIME_ZONE * /;
 / *! 40103 सेट TIME_ZONE = '+ 00:00' * /;
 / *; 40014 SET @OLD_UNIQUE_CHECKS = @@ UNIQUE_CHECKS, UNIQUE_CHECKS = 0 * /;
 / *; 40014 SET @OLD_FOREIGN_KEY_CHECKS = @@ FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS = 0 * /;
 / *; 40101 SET @OLD_SQL_MODE = @@ SQL_MODE, SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO' * /;
 / *; 40111 SET @OLD_SQL_NOTES = @@ SQL_NOTES, SQL_NOTES = 0 * /;
 / *; 40103 सेट TIME_ZONE = @ OLD_TIME_ZONE * /;

 / *! 40101 सेट SQL_MODE = @ OLD_SQL_MODE * /;
 / *; 40014 SET FOREIGN_KEY_CHECKS = @ OLD_FOREIGN_KEY_CHECKS * /;
 / *; 40014 SET UNIQUE_CHECKS = @ OLD_UNIQUE_CHECKS * /;
 / *; 40101 सेट करें CHARACTER_SET_CLIENT = @ OLD_CHARACTER_SET_CLIENT * /;
 / *; 40101 सेट करें CHARACTER_SET_RESULTS = @ OLD_CHARACTER_SET_RESULTS * /;
 / *; 40101 सेट करें COLLATION_CONNECTION = @ OLD_COLLATION_CONNECTION * /;
 / *! 40111 SET SQL_NOTES = @ OLD_SQL_NOTES * /;

कभी-कभी mysqldump यह भी शपथ ले सकता है कि वह mysql.time_zone_name तालिका में नहीं लिख सकता है:
  mysqldump: '/ *! 40103 सेट TIME_ZONE =' + 00:00 '* /' निष्पादित नहीं कर सका: तालिका 'mysql.time_zone_name' मौजूद नहीं है (1146) 
, लेकिन यह --skip-tz-utc विकल्प द्वारा हल किया गया है

डेटा रिकवरी


तो चलिए थोड़ा और गहराई में जाते हैं कि MySQL डेटाबेस की जानकारी कैसे स्टोर करता है। MySQL के संदर्भ में आधार वह निर्देशिका है जिसके अंदर तालिका परिभाषाएँ, अनुक्रमित और डेटा संग्रहीत हैं (InnoDB के मामले में, केवल तालिका परिभाषा निर्देशिका में संग्रहीत की जाती है, और डेटा एक अलग फ़ाइल में संग्रहीत होता है)। हमारे डेटाबेस को देखने के लिए MySQL के लिए, यह करने की आवश्यकता है कि निर्देशिका को अंदर / var / lib / mysql /
डेटाबेस के अंदर टेबल और डेटा प्राप्त करने के लिए, हमें वहां मौजूद सभी फ़ाइलों को पुनर्स्थापित करना होगा।
प्रक्रियाओं और कार्यों को मुख्य डेटाबेस में संग्रहीत नहीं किया जाता है, लेकिन खरीद तालिका में mysql डेटाबेस में निहित है - इसलिए, इस डेटाबेस को भी पुनर्स्थापित करने की आवश्यकता होगी।
कार्य इस तथ्य से सुगम है कि mysqld प्रक्रिया शुरू हो गई है और हटाए गए फ़ाइलों के लिए खुला फ़ाइल डिस्क्रिप्टर रखता है, और सिस्टम तब तक फ़ाइल को नहीं हटाता है जब तक कि डिस्क्रिप्टर बंद नहीं हो जाता। / Proc फ़ाइल सिस्टम इन फ़ाइलों को / proc / [pid] / fd / * के लिंक के माध्यम से पहुँच प्रदान करता है
 # ls -l / proc / 2544 / fd /
 कुल ०
 lr-x ------ 1 रूट रूट 64 Jun 22 12:05 0 -> / देव / अशक्त
 l-wx ------ 1 रूट रूट 64 Jun 22 12:05 1 -> /var/log/mysqld.log
 lrwx ------ 1 रूट रूट 64 Jun 22 12:05 10 -> सॉकेट: [9786]
 lrwx ------ 1 रूट रूट 64 Jun 22 12:05 11 -> / tmp / ibo0UVMZ (हटाए गए)
 lrwx ------ 1 रूट रूट 64 Jun 22 12:05 12 -> सॉकेट: [9787]
 lrwx ------ 1 रूट रूट 64 Jun 22 12:05 13 -> /var/lib/mysql/mysql/host.MYI (हटाए गए)
 ...
 lrwx ------ 1 रूट रूट 64 Jun 22 12:05 28 -> /var/lib/mysql/prod/table1.MYI (हटाए गए)
 lrwx ------ 1 रूट रूट 64 Jun 22 12:05 29 -> /var/lib/mysql/prod/table1.MYD (हटाए गए)
 ...

हम डेटाबेस के नामों को खोजने और उन्हें पुनर्स्थापित करने के लिए इसका उपयोग करेंगे, केवल निर्देशिका के अंदर / var / lib / mysql / को फ़िल्टर करेंगे और उन्हें उसी स्थान पर बनाएंगे:
 # ls -l / proc / 2544 / fd / |  grep / var / lib / mysql / |  cut -d '' -f11 |  cut -d / -f 5.6 |  grep / |  cut -d / -f1 |  सॉर्ट -यू
 mysql
 ठेस
 # ls -l / proc / 2544 / fd / |  grep / var / lib / mysql / |  cut -d '' -f11 |  cut -d / -f 5.6 |  grep / |  cut -d / -f1 |  सॉर्ट -यू |  xargs -I {} mkdir -v / var / lib / mysql / {}
 mkdir: निर्मित निर्देशिका `/ var / lib / mysql / mysql '
 mkdir: निर्मित निर्देशिका `/ var / lib / mysql / prod '

mysql अब अड्डों को देखता है:
 mysql> डेटाबेस दिखाएं;
 + -------------------- +
 |  डेटाबेस |
 + -------------------- +
 |  information_schema | 
 |  mysql | 
 |  ठेस | 
 + -------------------- +
 सेट में 3 पंक्तियाँ (0.00 सेकंड)

लेकिन mysqldump अभी भी शून्य निर्यात करेगा। हम इसे ठीक करने की कोशिश करेंगे, बाकी फाइलें जो अभी भी प्रक्रिया द्वारा खुली हैं, उन्हें पुनर्स्थापित करें। ऐसा करने के लिए, / var / lib / mysql / से फ़ाइलों को / proc में लिंक करें:
 # ls -l / proc / 2544 / fd / |  grep / var / lib / mysql / |  कट -d '' -f9,11 |  awk '{cmd = "ln -s / proc / 2544 / fd /" $ 1 "" $ 2; प्रिंट (cmd); सिस्टम (cmd);};
 ln -s / proc / 2544 / fd / 13 /var/lib/mysql/mysql/host/YI
 ln -s / proc / 2544 / fd / 14 /var/lib/mysql/mysql/host/YD
 ...
 ln -s / proc / 2544 / fd / 3 / var / lib / mysql / ibdata1
 ...
 ln -s / proc / 2544 / fd / 38 /var/lib/mysql/prod/table.gov.in
 ln -s / proc / 2544 / fd / 9 / var / lib / mysql / ib_logfile1
 ...

इस ऑपरेशन के बाद, mysqldump अभी भी एक शून्य लौटाता है, और यदि आप एक विशिष्ट तालिका निर्यात करने के लिए कहते हैं, तो यह शपथ लेगा कि ऐसी तालिका मौजूद नहीं है:
 # mysqldump --protocol tcp --skip-tz-utc prod table2
 mysqldump: तालिका नहीं मिली: "table2"

 # mysql --protocol tcp
 mysql> उत्पादों का उपयोग करें;
 डेटाबेस बदल गया

 mysql> टेबल दिखाएं;
 खाली सेट (0.00 सेकंड)

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

हालाँकि, विवरण फ़ाइल की अनुपस्थिति तालिकाओं से डेटा की प्रत्यक्ष प्राप्ति को रोकती नहीं है:
 mysql> table1 से गिनती (*) का चयन करें;
 + ---------- +
 |  गिनती (*) |
 + ---------- +
 |  100 | 
 + ---------- +
 1 पंक्ति में सेट (0.00 सेकंड)

 mysql> table1 सीमा 0.5 से * का चयन करें;
 + ---- + ------------------------------------- +
 |  आईडी |  वी |
 + ---- + ------------------------------------- +
 |  1 |  b026324c6904b2a9cb4b88d6d61c81d1 - | 
 |  2 |  26ab0db90d72e28ad0ba1e22ee510510 - | 
 |  3 |  6d7fce9fee471194aa8b5b6e47267f03 - | 
 |  4 |  48a24b70a0b376535542b996af517398 - | 
 |  5 |  1dcca23355272056f04fe8bf20edfce0 - | 
 + ---- + ------------------------------------- +
 सेट में 5 पंक्तियाँ (0.00 सेकंड)

 mysql> table2 सीमा 0.5 से * का चयन करें;
 + ---- + ------------------------------------- +
 |  आईडी |  वी |
 + ---- + ------------------------------------- +
 |  1 |  b026324c6904b2a9cb4b88d6d61c81d1 - | 
 |  2 |  26ab0db90d72e28ad0ba1e22ee510510 - | 
 |  3 |  6d7fce9fee471194aa8b5b6e47267f03 - | 
 |  4 |  48a24b70a0b376535542b996af517398 - | 
 |  5 |  1dcca23355272056f04fe8bf20edfce0 - | 
 + ---- + ------------------------------------- +
 सेट में 5 पंक्तियाँ (0.00 सेकंड)

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

निष्कर्ष


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

Source: https://habr.com/ru/post/In122424/


All Articles