A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

ro-eachdraidheil

Thachair e mar sin gun deach ionnsaigh a thoirt air an fhrithealaiche le bhìoras ransomware, a dh’ fhàg, le “tubaist fortanach,” gu ìre na faidhlichean .ibd (faidhlichean dàta amh de chlàran innodb) gun suathadh, ach aig an aon àm a chuir na faidhlichean .fpm a-steach gu tur ( faidhlichean structarail). Anns a 'chùis seo, dh' fhaodadh .idb a bhith air a roinn mar:

  • le ùmhlachd do ath-nuadhachadh tro innealan àbhaisteach agus stiùiridhean. Airson leithid de chùisean, tha sàr-mhath fàs;
  • clàran air an crioptachadh gu ìre. Is e bùird mòra a tha seo sa mhòr-chuid, airson nach robh (mar a tha mi a’ tuigsinn) aig an luchd-ionnsaigh gu leòr RAM airson làn chrioptachadh;
  • Uill, bùird làn chrioptaichte nach gabh an toirt air ais.

Bha e comasach faighinn a-mach dè an roghainn a bhuineas do na clàran le bhith dìreach ga fhosgladh ann an deasaiche teacsa sam bith fon chòdachadh a bha thu ag iarraidh (anns a’ chùis agam is e UTF8 a th ’ann) agus dìreach coimhead air an fhaidhle airson làthaireachd raointean teacsa, mar eisimpleir:

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

Cuideachd, aig toiseach an fhaidhle chì thu àireamh mhòr de 0 bytes, agus bhìorasan a bhios a 'cleachdadh an algairim crioptachadh bloc (an fheadhainn as cumanta) mar as trice a' toirt buaidh orra cuideachd.
A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

Anns a 'chùis agam, dh'fhàg an luchd-ionnsaigh sreang 4-byte (1, 0, 0, 0) aig deireadh gach faidhle crioptaichte, a rinn an obair nas sìmplidhe. Gus faidhlichean gun dìon a lorg, bha an sgriobt gu leòr:

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)

Mar sin, thionndaidh e a-mach faidhlichean a lorg a bhuineas don chiad sheòrsa. Tha an dàrna fear a 'toirt a-steach tòrr obair làimhe, ach bha na chaidh a lorg mar-thà gu leòr. Bhiodh a h-uile dad gu math, ach feumaidh fios a bhith agad structar gu tur mionaideach agus (gu dearbh) dh'èirich cùis gum feumadh mi a bhith ag obair le bòrd a bha tric ag atharrachadh. Cha robh cuimhne aig duine an deach an seòrsa raoin atharrachadh neo an deach colbh ùr a chur ris.

Gu mì-fhortanach, cha b 'urrainn dha Wilds City cuideachadh le leithid de chùis, agus is e sin as coireach gu bheil an artaigil seo ga sgrìobhadh.

Faigh chun phuing

Tha structar clàr ann bho chionn 3 mìosan nach eil a 'freagairt ris an fhear a th' ann an-dràsta (is dòcha aon raon, agus 's dòcha barrachd). Structar clàr:

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)
); 

Anns a 'chùis seo, feumaidh tu a thoirt a-mach:

  • id_point anns(11);
  • id_user anns(11);
  • date_start DATETIME;
  • date_finish CEANN-LATHA.

Airson faighinn air ais, bithear a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle .ibd, agus an uairsin gan tionndadh gu cruth a ghabhas leughadh. Leis gu bheil sinn airson na tha a dhìth oirnn a lorg, chan fheum sinn ach mion-sgrùdadh a dhèanamh air seòrsachan dàta leithid int agus datatime, cha toir an artaigil cunntas ach orra, ach uaireannan bheir sinn iomradh cuideachd air seòrsachan dàta eile, a chuidicheas ann an tachartasan eile den aon seòrsa.

Trioblaid 1: bha luachan NULL aig raointean le seòrsaichean DATETIME agus TEXT, agus tha iad dìreach air an sgiobadh san fhaidhle, air sgàth seo, cha robh e comasach an structar ath-nuadhachadh anns a’ chùis agam a dhearbhadh. Anns na colbhan ùra, bha an luach bunaiteach null, agus dh’ fhaodadh pàirt den ghnothach a bhith air a chall air sgàth an t-suidheachaidh innodb_flush_log_at_trx_commit = 0, agus mar sin dh’ fheumadh ùine a bharrachd a chaitheamh gus an structar a dhearbhadh.

Trioblaid 2: bu chòir a thoirt fa-near gum bi sreathan a chaidh a sguabadh às tro DELETE uile anns an fhaidhle ibd, ach le ALTER TABLE cha tèid an structar aca ùrachadh. Mar thoradh air an sin, faodaidh structar an dàta atharrachadh bho thoiseach an fhaidhle gu deireadh. Ma bhios tu gu tric a’ cleachdadh OPTIMIZE TABLE, chan eil e coltach gum bi thu a’ tighinn tarsainn air a leithid de dhuilgheadas.

Thoir aire, tha an dreach DBMS a’ toirt buaidh air an dòigh sa bheil dàta air a stòradh, agus dh’ fhaodadh nach obraich an eisimpleir seo airson tionndaidhean mòra eile. Anns a 'chùis agam, chaidh an tionndadh uinneagan de mariadb 10.1.24 a chleachdadh. Cuideachd, ged a tha thu ann am mariadb ag obair le bùird InnoDB, gu dearbh tha iad XtraDB, a tha a’ dùnadh a-mach iomchaidheachd a’ mhodh le InnoDB mysql.

Mion-sgrùdadh faidhle

Ann am python, seòrsa dàta bytes() a’ taisbeanadh dàta Unicode an àite seata àireamhan cunbhalach. Ged as urrainn dhut am faidhle fhaicinn san fhoirm seo, airson goireasachd faodaidh tu na bytes a thionndadh gu cruth àireamhach le bhith ag atharrachadh an t-sreath byte gu sreath àbhaisteach (liosta (example_byte_array)). Ann an suidheachadh sam bith, tha an dà dhòigh freagarrach airson mion-sgrùdadh.

Às deidh dhut coimhead tro ghrunn fhaidhlichean ibd, gheibh thu na leanas:

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

A bharrachd air an sin, ma roinneas tu am faidhle leis na prìomh fhaclan sin, gheibh thu eadhon blocaichean dàta sa mhòr-chuid. Cleachdaidh sinn infimum mar roinnear.

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

Beachdachadh inntinneach: airson bùird le glè bheag de dhàta, eadar lag agus supremum tha comharradh air an àireamh de shreathan sa bhloc.

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd - clàr deuchainn le sreath 1

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd - clàr deuchainn le 2 shreath

Faodar an clàr sreath sreath[0] a sheachnadh. Às deidh dhomh coimhead troimhe, cha robh e comasach dhomh fhathast an dàta clàr amh a lorg. As dualtaiche, tha am bloc seo air a chleachdadh gus clàran-amais agus iuchraichean a stòradh.
A’ tòiseachadh le clàr [1] agus ga eadar-theangachadh gu sreath àireamhach, chì thu cuid de phàtranan mu thràth, is iad sin:

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

Is iad sin int luachan air an stòradh ann an sreang. Tha a’ chiad byte a’ sealltainn a bheil an àireamh dearbhach no àicheil. Anns a 'chùis agam, tha na h-àireamhan uile deimhinneach. Bho na 3 bytes a tha air fhàgail, faodaidh tu an àireamh a dhearbhadh leis a’ ghnìomh a leanas. Sgriobt:

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

Mar eisimpleir, 128, 0, 0, 1 = 1, No 128, 0, 75, 108 = 19308.
Bha prìomh iuchair aig a’ chlàr le àrdachadh fèin-ghluasadach, agus gheibhear e an seo cuideachd

A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd

An dèidh coimeas a dhèanamh eadar an dàta bho na clàran deuchainn, chaidh innse gu bheil an nì DATETIME air a dhèanamh suas de 5 bytes agus thòisich e le 153 (a rèir coltais a’ comharrachadh amannan bliadhnail). Leis gu bheil an raon DATTIME eadar ‘1000-01-01’ gu ‘9999-12-31’, tha mi a’ smaoineachadh gum faodadh an àireamh de bytes a bhith eadar-dhealaichte, ach anns a’ chùis agamsa, tha an dàta a’ tuiteam anns an ùine bho 2016 gu 2019, agus mar sin gabhaidh sinn ris. sin 5 bytes gu leòr.

Gus an ùine gun diogan a dhearbhadh, chaidh na gnìomhan a leanas a sgrìobhadh. Sgriobt:

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}

Cha robh e comasach gnìomh gnìomh a sgrìobhadh airson na bliadhna agus na mìos, agus mar sin bha agam ri a sheacadh. Sgriobt:

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

Tha mi cinnteach ma chaitheas tu n ùine, gun gabh a’ mhì-thuigse seo a cheartachadh.
An ath rud, gnìomh a thilleas nì ceann-latha bho shreang. Sgriobt:

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)

Air a stiùireadh gus luachan a tha tric a’ nochdadh a-rithist a lorg bho int, int, datetime, datetime A’ faighinn air ais dàta bho chlàran XtraDB às aonais faidhle structair a’ cleachdadh mion-sgrùdadh byte-by-byte den fhaidhle ibd, tha e coltach gur e seo a tha a dhìth ort. A bharrachd air an sin, chan eil an leithid de shreath air ath-aithris dà uair gach loidhne.

A’ cleachdadh abairt àbhaisteach, lorgaidh sinn an dàta riatanach:

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)

Thoir an aire, nuair a bhios tu a’ rannsachadh a’ cleachdadh an abairt seo, nach bi e comasach luachan NULL a dhearbhadh anns na raointean a tha a dhìth, ach anns a’ chùis agam chan eil seo deatamach. An uairsin thèid sinn tro na lorg sinn ann an lùb. Sgriobt:

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)

Gu fìrinneach, is e sin uile, is e an dàta bhon raon thoraidhean an dàta a tha a dhìth oirnn. ###PS.###
Tha mi a 'tuigsinn nach eil an dòigh seo freagarrach airson a h-uile duine, ach is e prìomh amas an artaigil gnìomh a bhrosnachadh seach a bhith a' fuasgladh na duilgheadasan agad gu lèir. Tha mi a’ smaoineachadh gur e am fuasgladh as ceart tòiseachadh a’ sgrùdadh a’ chòd stòr thu fhèin mariadb, ach air sgàth ùine chuingealaichte, bha e coltach gur e am modh gnàthach as luaithe.

Ann an cuid de chùisean, às deidh dhut mion-sgrùdadh a dhèanamh air an fhaidhle, bidh e comasach dhut an structar tuairmseach a dhearbhadh agus a thoirt air ais le bhith a ’cleachdadh aon de na dòighean àbhaisteach bho na ceanglaichean gu h-àrd. Bidh seo tòrr nas ceart agus ag adhbhrachadh nas lugha de dhuilgheadasan.

Source: www.habr.com

Cuir beachd ann