ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

prehistory

ائين ئي ٿيو آهي ته سرور تي هڪ ransomware وائرس جو حملو ٿيو، جنهن، هڪ ”خوش قسمت حادثي“ جي ڪري، جزوي طور .ibd فائلن کي ڇڏي ڏنو (انوڊ بي ٽيبل جي خام ڊيٽا فائلن) کي اڻ ڇهيو، پر ساڳئي وقت مڪمل طور تي .fpm فائلن کي انڪريپٽ ڪيو ( ڍانچي فائلون). هن معاملي ۾، .idb ۾ ورهائي سگهجي ٿو:

  • معياري اوزار ۽ گائيڊ ذريعي بحالي جي تابع. اهڙين حالتن لاء، اتي هڪ شاندار آهي ٿيڻ;
  • جزوي طور تي انڪوڊ ٿيل ٽيبل. گهڻو ڪري اهي وڏيون ٽيبلون آهن، جن لاءِ (جيئن مان سمجهان ٿو) حملي آورن وٽ پوري انڪرپشن لاءِ ڪافي RAM نه هئي.
  • خير، مڪمل طور تي مرڪوز ٿيل جدول جيڪي بحال نٿا ٿي سگهن.

اهو طئي ڪرڻ ممڪن هو ته ٽيبل ڪهڙي آپشن سان تعلق رکن ٿا صرف ان کي کولڻ سان ڪنهن به ٽيڪسٽ ايڊيٽر ۾ گهربل انڪوڊنگ تحت (منهنجي صورت ۾ اهو UTF8 آهي) ۽ صرف ٽيڪسٽ فيلڊز جي موجودگي لاءِ فائل کي ڏسڻ ، مثال طور:

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

انهي سان گڏ، فائل جي شروعات ۾ توهان 0 بائيٽ جي وڏي تعداد جو مشاهدو ڪري سگهو ٿا، ۽ وائرس جيڪي استعمال ڪن ٿا بلاڪ انڪرپشن الگورٿم (سڀ کان وڌيڪ عام) عام طور تي انهن کي پڻ متاثر ڪن ٿا.
ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

منهنجي حالت ۾، حملي ڪندڙن هر انڪريپٽ ٿيل فائل جي آخر ۾ 4-بائيٽ اسٽرنگ (1، 0، 0، 0) ڇڏي ڏنو، جيڪو ڪم کي آسان بڻائي ٿو. اڻڄاتل فائلن کي ڳولڻ لاء، اسڪرپٽ ڪافي هئي:

def opened(path):
    files = os.listdir(path)
    for f in files:
        if os.path.isfile(path + f):
            yield path + f

for full_path in opened("C:somepath"):
    file = open(full_path, "rb")
    last_string = ""
    for line in file:
        last_string = line
        file.close()
    if (last_string[len(last_string) -4:len(last_string)]) != (1, 0, 0, 0):
        print(full_path)

اهڙيء طرح، ان کي پهريون قسم سان لاڳاپيل فائلون ڳولڻ لاء ٻاهر موٽيو. ٻئي ۾ تمام گهڻو دستي ڪم شامل آهي، پر جيڪو مليو اهو اڳ ۾ ئي ڪافي هو. سڀ ڪجھ ٺيڪ ٿي ويندو، پر توھان کي ڄاڻڻ جي ضرورت آھي بلڪل صحيح ساخت ۽ (يقينا) هڪ ڪيس پيدا ٿيو ته مون کي بار بار تبديل ٿيندڙ ٽيبل سان ڪم ڪرڻو پيو. ڪنهن کي به ياد نه آهي ته فيلڊ جو قسم تبديل ڪيو ويو يا هڪ نئون ڪالم شامل ڪيو ويو.

وائلڊ سٽي، بدقسمتي سان، اهڙي معاملي ۾ مدد نه ڪري سگهيو، ڇو ته هي مضمون لکيو پيو وڃي.

نقطي تي وڃو

3 مھينا اڳ جي ھڪڙي ٽيبل جي ھڪڙي جوڙجڪ آھي جيڪا موجوده ھڪڙي سان ٺھيل نه آھي (ممڪن طور ھڪڙي فيلڊ، ۽ ممڪن آھي وڌيڪ). ٽيبل جي جوڙجڪ:

CREATE TABLE `table_1` (
    `id` INT (11),
    `date` DATETIME ,
    `description` TEXT ,
    `id_point` INT (11),
    `id_user` INT (11),
    `date_start` DATETIME ,
    `date_finish` DATETIME ,
    `photo` INT (1),
    `id_client` INT (11),
    `status` INT (1),
    `lead__time` TIME ,
    `sendstatus` TINYINT (4)
); 

هن معاملي ۾، توهان کي ڪڍڻ جي ضرورت آهي:

  • id_point int (11)؛
  • id_user int (11)؛
  • date_start DATETIME؛
  • date_finish DATETIME.

بحاليءَ لاءِ، .ibd فائل جو بائيٽ بائيٽ تجزيو استعمال ڪيو ويندو آھي، ان کان پوءِ انھن کي وڌيڪ پڙھي سگھجي ٿو. جيئن ته اسان کي ڇا ڳولڻ جي ضرورت آهي، اسان کي صرف ڊيٽا جي قسمن جو تجزيو ڪرڻ جي ضرورت آهي جهڙوڪ int ۽ datatime، آرٽيڪل صرف انهن کي بيان ڪندو، پر ڪڏهن ڪڏهن اسان ٻين ڊيٽا جي قسمن جو حوالو پڻ ڏينداسين، جيڪي ٻين ساڳئي واقعن ۾ مدد ڪري سگھن ٿيون.

مسئلو 1: DATETIME ۽ TEXT قسمن جي فيلڊن ۾ NULL قدر هئا، ۽ اهي صرف فائل ۾ ڇڏيا ويا آهن، ان جي ڪري، منهنجي صورت ۾ بحال ڪرڻ لاء ساخت جو تعين ڪرڻ ممڪن نه هو. نون ڪالمن ۾، ڊفالٽ ويل نيل هئي، ۽ ٽرانزيڪشن جو حصو innodb_flush_log_at_trx_commit = 0 سيٽنگ جي ڪري گم ٿي سگهي ٿو، تنهنڪري ساخت کي طئي ڪرڻ لاءِ اضافي وقت خرچ ڪرڻو پوندو.

مسئلو 2: ان ڳالهه کي ذهن ۾ رکڻ گهرجي ته DELETE ذريعي ڊهي وڃڻ واريون قطارون سڀ ibd فائل ۾ هونديون، پر ALTER TABLE سان انهن جي جوڙجڪ کي اپڊيٽ نه ڪيو ويندو. نتيجي طور، ڊيٽا جي جوڙجڪ فائل جي شروعات کان ان جي آخر تائين مختلف ٿي سگهي ٿي. جيڪڏهن توهان اڪثر استعمال ڪندا آهيو OPTIMIZE TABLE، ته پوءِ توهان کي اهڙي مسئلي سان منهن ڏيڻ ممڪن ناهي.

ڌيان ڏيڻ, DBMS ورزن ڊيٽا کي محفوظ ڪرڻ جي طريقي تي اثر انداز ٿئي ٿو، ۽ اهو مثال ٻين وڏن نسخن لاء ڪم نه ڪري سگھي ٿو. منهنجي حالت ۾، mariadb 10.1.24 جو ونڊوز ورزن استعمال ڪيو ويو. گڏوگڏ، جيتوڻيڪ mariadb ۾ توهان InnoDB جدولن سان ڪم ڪندا آهيو، حقيقت ۾ اهي آهن ايڪسٽرا ڊي بي، جيڪو InnoDB mysql سان طريقي جي قابل اطلاق کي خارج ڪري ٿو.

فائل جو تجزيو

پٿون ۾، ڊيٽا جو قسم بائيٽ() يونيڪوڊ ڊيٽا کي انگن جي باقاعده سيٽ جي جاء تي ڏيکاري ٿو. جيتوڻيڪ توهان هن فارم ۾ فائل ڏسي سگهو ٿا، سهولت لاءِ توهان بائيٽ کي عددي شڪل ۾ تبديل ڪري سگهو ٿا بائيٽ ايري کي باقاعده صف ۾ تبديل ڪري (list(example_byte_array)). ڪنهن به صورت ۾، ٻنهي طريقن جي تجزيي لاء مناسب آهن.

ڪيترن ئي ibd فائلن کي ڳولڻ کان پوء، توهان هيٺ ڏنل ڳولي سگهو ٿا:

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

ان کان علاوه، جيڪڏهن توهان فائل کي انهن لفظن سان ورهايو ٿا، توهان کي گهڻو ڪري ڊيٽا جا بلاڪ ملندا. اسان انفيمم کي تقسيم ڪندڙ طور استعمال ڪنداسين.

table = table.split("infimum".encode())

هڪ دلچسپ مشاهدو: ڊيٽا جي ننڍڙي مقدار سان ٽيبل لاء، انفيمم ۽ سپريمم جي وچ ۾ بلاڪ ۾ قطار جي تعداد ڏانهن اشارو آهي.

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ - پهرين قطار سان ٽيسٽ ٽيبل

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ - ٽيسٽ ٽيبل 2 قطارن سان

قطار جي صف واري جدول[0] کي ڇڏي سگھجي ٿو. ان کي ڏسڻ کان پوء، مان اڃا تائين خام ٽيبل ڊيٽا ڳولڻ جي قابل نه هو. گهڻو ڪري، هي بلاڪ انڊيڪس ۽ ڪيچ کي ذخيرو ڪرڻ لاء استعمال ڪيو ويندو آهي.
ٽيبل[1] سان شروع ڪندي ۽ ان کي عددي صف ۾ ترجمو ڪندي، توهان اڳ ۾ ئي ڪجهه نمونن کي نوٽيس ڪري سگهو ٿا، يعني:

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

اهي هڪ اسٽرنگ ۾ محفوظ ڪيل int قدر آهن. پهريون بائيٽ ظاهر ڪري ٿو ته نمبر مثبت يا منفي آهي. منهنجي حالت ۾، سڀ انگ مثبت آهن. باقي 3 بائيٽس مان، توھان ھيٺ ڏنل فنڪشن استعمال ڪندي نمبر جو تعين ڪري سگھو ٿا. اسڪرپٽ:

def find_int(val: str):  # example '128, 1, 2, 3'
    val = [int(v) for v in  val.split(", ")]
    result_int = val[1]*256**2 + val[2]*256*1 + val[3]
    return result_int

مثال طور، 128، 0، 0، 1 = 1يا 128، 0، 75، 108 = 19308.
ٽيبل کي آٽو-وڌائڻ سان گڏ هڪ پرائمري ڪنجي هئي، ۽ اهو پڻ ملي سگهي ٿو هتي

ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ

ٽيسٽ جدولن مان ڊيٽا جي مقابلي ۾، اهو ظاهر ڪيو ويو آهي ته DATETIME اعتراض 5 بائيٽ تي مشتمل آهي ۽ 153 سان شروع ٿئي ٿو (گهڻو ڪري سالياني وقفن کي ظاهر ڪري ٿو). جيئن ته DATTIME جي حد '1000-01-01' کان '9999-12-31' تائين آهي، منهنجو خيال آهي ته بائيٽ جو تعداد مختلف ٿي سگهي ٿو، پر منهنجي صورت ۾، ڊيٽا 2016 کان 2019 جي عرصي ۾ اچي ٿو، تنهنڪري اسان فرض ڪنداسين اهو 5 بائيٽ ڪافي آهي.

سيڪنڊن کان سواءِ وقت جو تعين ڪرڻ لاءِ ھيٺ ڏنل ڪم لکجي ويا. اسڪرپٽ:

day_ = lambda x: x % 64 // 2  # {x,x,X,x,x }

def hour_(x1, x2):  # {x,x,X1,X2,x}
    if x1 % 2 == 0:
        return x2 // 16
    elif x1 % 2 == 1:
        return x2 // 16 + 16
    else:
        raise ValueError

min_ = lambda x1, x2: (x1 % 16) * 4 + (x2 // 64)  # {x,x,x,X1,X2}

سال ۽ مھيني لاءِ فعلي ڪم لکڻ ممڪن نه ھو، ان ڪري مون کي ھيڪ ڪرڻو پيو. اسڪرپٽ:

ym_list = {'2016, 1': '153, 152, 64', '2016, 2': '153, 152, 128', 
           '2016, 3': '153, 152, 192', '2016, 4': '153, 153, 0',
           '2016, 5': '153, 153, 64', '2016, 6': '153, 153, 128', 
           '2016, 7': '153, 153, 192', '2016, 8': '153, 154, 0', 
           '2016, 9': '153, 154, 64', '2016, 10': '153, 154, 128', 
           '2016, 11': '153, 154, 192', '2016, 12': '153, 155, 0',
           '2017, 1': '153, 155, 128', '2017, 2': '153, 155, 192', 
           '2017, 3': '153, 156, 0', '2017, 4': '153, 156, 64',
           '2017, 5': '153, 156, 128', '2017, 6': '153, 156, 192',
           '2017, 7': '153, 157, 0', '2017, 8': '153, 157, 64',
           '2017, 9': '153, 157, 128', '2017, 10': '153, 157, 192', 
           '2017, 11': '153, 158, 0', '2017, 12': '153, 158, 64', 
           '2018, 1': '153, 158, 192', '2018, 2': '153, 159, 0',
           '2018, 3': '153, 159, 64', '2018, 4': '153, 159, 128', 
           '2018, 5': '153, 159, 192', '2018, 6': '153, 160, 0',
           '2018, 7': '153, 160, 64', '2018, 8': '153, 160, 128',
           '2018, 9': '153, 160, 192', '2018, 10': '153, 161, 0', 
           '2018, 11': '153, 161, 64', '2018, 12': '153, 161, 128',
           '2019, 1': '153, 162, 0', '2019, 2': '153, 162, 64', 
           '2019, 3': '153, 162, 128', '2019, 4': '153, 162, 192', 
           '2019, 5': '153, 163, 0', '2019, 6': '153, 163, 64',
           '2019, 7': '153, 163, 128', '2019, 8': '153, 163, 192',
           '2019, 9': '153, 164, 0', '2019, 10': '153, 164, 64', 
           '2019, 11': '153, 164, 128', '2019, 12': '153, 164, 192',
           '2020, 1': '153, 165, 64', '2020, 2': '153, 165, 128',
           '2020, 3': '153, 165, 192','2020, 4': '153, 166, 0', 
           '2020, 5': '153, 166, 64', '2020, 6': '153, 1, 128',
           '2020, 7': '153, 166, 192', '2020, 8': '153, 167, 0', 
           '2020, 9': '153, 167, 64','2020, 10': '153, 167, 128',
           '2020, 11': '153, 167, 192', '2020, 12': '153, 168, 0'}

def year_month(x1, x2):  # {x,X,X,x,x }

    for key, value in ym_list.items():
        key = [int(k) for k in key.replace("'", "").split(", ")]
        value = [int(v) for v in value.split(", ")]
        if x1 == value[1] and x2 // 64 == value[2] // 64:
            return key
    return 0, 0

مون کي پڪ آهي ته جيڪڏهن توهان ڪجهه وقت گذاريو ته اها غلط فهمي درست ٿي سگهي ٿي.
اڳيون، هڪ فنڪشن جيڪو هڪ تار کان هڪ datetime اعتراض واپس ڪري ٿو. اسڪرپٽ:

def find_data_time(val:str):
    val = [int(v) for v in val.split(", ")]
    day = day_(val[2])
    hour = hour_(val[2], val[3])
    minutes = min_(val[3], val[4])
    year, month = year_month(val[1], val[2])
    return datetime(year, month, day, hour, minutes)

int، int، datetime، datetime مان بار بار بار بار ويلن کي ڳولڻ لاءِ منظم ڪيو ويو ibd فائل جي بائيٽ بائيٽ تجزيو استعمال ڪندي بغير ڪنهن ساخت واري فائل جي XtraDB جدولن مان ڊيٽا کي بحال ڪرڻ، اهو لڳي ٿو ته هي آهي جيڪو توهان جي ضرورت آهي. ان کان علاوه، اهڙي ترتيب هر لڪير ۾ ٻه ڀيرا نه ورجائي ويندي آهي.

باقاعده اظهار کي استعمال ڪندي، اسان کي ضروري ڊيٽا ملن ٿا:

fined = re.findall(r'128, d*, d*, d*, 128, d*, d*, d*, 153, 1[6,5,4,3]d, d*, d*, d*, 153, 1[6,5,4,3]d, d*, d*, d*', int_array)

مهرباني ڪري نوٽ ڪريو ته جڏهن هن اظهار کي استعمال ڪندي ڳولهي رهيا آهيو، اهو ممڪن نه هوندو ته NULL قدرن کي گهربل فيلڊ ۾، پر منهنجي صورت ۾ اهو نازڪ ناهي. ان کان پوء اسان ان ذريعي وڃون ٿا جيڪو اسان کي لوپ ۾ مليو. اسڪرپٽ:

result = []
for val in fined:
    pre_result = []
    bd_int  = re.findall(r"128, d*, d*, d*", val)
    bd_date= re.findall(r"(153, 1[6,5,4,3]d, d*, d*, d*)", val)
    for it in bd_int:
        pre_result.append(find_int(bd_int[it]))
    for bd in bd_date:
        pre_result.append(find_data_time(bd))
    result.append(pre_result)

دراصل، اهو سڀ ڪجهه آهي، نتيجن جي صف مان ڊيٽا اها ڊيٽا آهي جيڪا اسان کي گهربل آهي. ###PS.###
مان سمجهان ٿو ته اهو طريقو هر ڪنهن لاءِ موزون ناهي، پر مضمون جو بنيادي مقصد توهان جي سڀني مسئلن کي حل ڪرڻ بجاءِ فوري عمل ڪرڻ آهي. منهنجو خيال آهي ته سڀ کان وڌيڪ صحيح حل اهو هوندو ته سورس ڪوڊ جو مطالعو شروع ڪيو وڃي ماري، پر محدود وقت جي ڪري، موجوده طريقو تمام تيز ترين لڳي رهيو هو.

ڪجهه حالتن ۾، فائل جي تجزيو ڪرڻ کان پوء، توهان تقريبن ڍانچي جو اندازو لڳائي سگهندا ۽ مٿي ڏنل لنڪ مان معياري طريقن مان هڪ استعمال ڪندي ان کي بحال ڪري سگهندا. اهو وڌيڪ صحيح ٿيندو ۽ گهٽ مسئلا پيدا ڪندو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو