prehistory
እንዲህ ሆነ አገልጋዩ በራንሰምዌር ቫይረስ ተጠቃ፣ እሱም "በዕድለኛ አደጋ" በከፊል የኢብዲ ፋይሎችን (ጥሬ የ innodb ሰንጠረዦችን ጥሬ ዳታ ፋይሎች) ሳይነኩ ትቷቸዋል፣ ነገር ግን በተመሳሳይ ጊዜ የኤፍፒኤም ፋይሎችን ሙሉ በሙሉ ያመሳጠረ () መዋቅር ፋይሎች). በዚህ ሁኔታ፣ .idb በሚከተሉት ሊከፈል ይችላል፡-
- በመደበኛ መሳሪያዎች እና መመሪያዎች በኩል ወደነበረበት መመለስ ተገዢ. ለእንደዚህ አይነት ጉዳዮች በጣም ጥሩ ነገር አለ
መሆን ; - በከፊል የተመሰጠሩ ሠንጠረዦች. በአብዛኛው እነዚህ ትላልቅ ጠረጴዛዎች ናቸው, ለዚህም (እንደገባኝ) አጥቂዎቹ ለሙሉ ምስጠራ በቂ ራም አልነበራቸውም;
- ደህና፣ ወደነበሩበት ሊመለሱ የማይችሉ ሙሉ በሙሉ የተመሰጠሩ ሰንጠረዦች።
በቀላሉ በማንኛውም የጽሑፍ አርታኢ ውስጥ በሚፈለገው ኢንኮዲንግ (በእኔ ሁኔታ UTF8 ነው) በመክፈት እና በቀላሉ የጽሑፍ መስኮች መኖራቸውን ፋይሉን በማየት ሰንጠረዦቹ የየትኛው አማራጭ እንደሆኑ ማወቅ ተችሏል ።
እንዲሁም በፋይሉ መጀመሪያ ላይ ብዙ ቁጥር ያላቸውን 0 ባይት መመልከት ይችላሉ፣ እና የማገጃ ምስጠራ ስልተ-ቀመር (በጣም የተለመደው) የሚጠቀሙ ቫይረሶች ብዙውን ጊዜ እነሱንም ይጎዳሉ።
በእኔ ሁኔታ አጥቂዎቹ በእያንዳንዱ ኢንክሪፕት የተደረገ ፋይል መጨረሻ ላይ ባለ 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)
ስለዚህ, የመጀመሪያው ዓይነት የሆኑ ፋይሎችን ለማግኘት ተገኘ. ሁለተኛው ብዙ የእጅ ሥራዎችን ያካትታል, ነገር ግን የተገኘው ነገር ቀድሞውኑ በቂ ነበር. ሁሉም ነገር ጥሩ ይሆናል, ግን ማወቅ ያስፈልግዎታል ፍጹም ትክክለኛ መዋቅር እና (በእርግጥ) በተደጋጋሚ ከሚለዋወጠው ጠረጴዛ ጋር መሥራት እንዳለብኝ አንድ ጉዳይ ተነሳ. የመስክ አይነት ተቀይሯል ወይም አዲስ አምድ መታከል ማንም አላስታውስም።
Wilds City, በሚያሳዝን ሁኔታ, በእንደዚህ አይነት ጉዳይ ላይ መርዳት አልቻለም, ለዚህም ነው ይህ ጽሑፍ የሚጻፈው.
ወደ ነጥቡ ግባ
ከ 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 አይነቶች ያላቸው መስኮች ባዶ እሴቶች ነበሯቸው፣ እና እነሱ በቀላሉ በፋይሉ ውስጥ ተዘለዋል፣ በዚህ ምክንያት በእኔ ሁኔታ ወደነበረበት ለመመለስ አወቃቀሩን ማወቅ አልተቻለም። በአዲሶቹ አምዶች ውስጥ፣ ነባሪው ዋጋ ባዶ ነበር፣ እና የግብይቱ አካል በ innodb_flush_log_at_trx_commit = 0 ቅንብር ምክንያት ሊጠፋ ይችላል፣ ስለዚህ አወቃቀሩን ለመወሰን ተጨማሪ ጊዜ ማውጣት አለበት።
ችግር 2በ DELETE በኩል የተሰረዙ ረድፎች ሁሉም በ ibd ፋይል ውስጥ እንደሚሆኑ ግምት ውስጥ መግባት አለበት ፣ ግን በALTER TABLE የእነሱ መዋቅር አይዘመንም። በውጤቱም, የውሂብ አወቃቀሩ ከፋይሉ መጀመሪያ እስከ መጨረሻው ሊለያይ ይችላል. ብዙ ጊዜ OPTIMIZE TABLEን የሚጠቀሙ ከሆነ እንደዚህ አይነት ችግር ሊያጋጥሙዎት አይችሉም።
ትኩረት ይስጡ፣ የዲቢኤምኤስ እትም ውሂብ በሚከማችበት መንገድ ላይ ተጽዕኖ ያሳድራል፣ እና ይህ ምሳሌ ለሌሎች ዋና ስሪቶች ላይሰራ ይችላል። በእኔ ሁኔታ, የዊንዶውስ የ mariadb 10.1.24 ስሪት ጥቅም ላይ ውሏል. እንዲሁም፣ በማሪአድብ ውስጥ ከ InnoDB ሠንጠረዦች ጋር ቢሰሩም፣ በእውነቱ እነሱ ናቸው።
የፋይል ትንተና
በፓይቶን፣ የውሂብ አይነት
በርካታ የ ibd ፋይሎችን ከተመለከቱ በኋላ የሚከተሉትን ማግኘት ይችላሉ።
በተጨማሪም ፋይሉን በእነዚህ ቁልፍ ቃላቶች ከከፋፈሉት, አብዛኛውን ጊዜ እንኳን የውሂብ ብሎኮች ያገኛሉ. ኢንፊሙምን እንደ አካፋይ እንጠቀማለን።
table = table.split("infimum".encode())
አንድ አስደሳች ምልከታ: አነስተኛ መጠን ያለው መረጃ ላላቸው ሰንጠረዦች, በአቅም ማነስ እና በሱፐርሙ መካከል በብሎክ ውስጥ ያሉትን የረድፎች ብዛት ጠቋሚ አለ.
- የሙከራ ሰንጠረዥ ከ 1 ኛ ረድፍ ጋር
- የሙከራ ጠረጴዛ ከ 2 ረድፎች ጋር
የረድፍ አደራደር ጠረጴዛ [0] ሊዘለል ይችላል። እሱን ከተመለከትኩ በኋላ፣ አሁንም የጥሬ ሠንጠረዥ መረጃ ማግኘት አልቻልኩም። ምናልባትም ይህ እገዳ ኢንዴክሶችን እና ቁልፎችን ለማከማቸት ያገለግላል።
ከሠንጠረዥ[1] ጀምሮ እና ወደ የቁጥር አደራደር መተርጎም፣ አንዳንድ ንድፎችን አስቀድመው ሊያስተውሉ ይችላሉ፣ እነሱም፡-
እነዚህ በሕብረቁምፊ ውስጥ የተከማቹ 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.
ሠንጠረዡ በራስ-መጨመር ዋና ቁልፍ ነበረው፣ እና እዚህም ሊገኝ ይችላል።
ከሙከራ ሠንጠረዦች የተገኘውን መረጃ ካነፃፅር በኋላ፣ የ 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
እርግጠኛ ነኝ ጊዜን የምታሳልፉ ከሆነ ይህ አለመግባባት ሊስተካከል ይችላል።
በመቀጠል የቀን ጊዜ ነገርን ከአንድ ሕብረቁምፊ የሚመልስ ተግባር። ስክሪፕት፡
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 ለማወቅ ተችሏል። , ይህ የሚያስፈልግህ ይመስላል. ከዚህም በላይ እንዲህ ዓይነቱ ቅደም ተከተል በአንድ መስመር ሁለት ጊዜ አይደገምም.
መደበኛ አገላለጽ በመጠቀም አስፈላጊውን ውሂብ እናገኛለን፡-
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 እሴቶችን መወሰን እንደማይቻል ልብ ይበሉ ፣ ግን በእኔ ሁኔታ ይህ ወሳኝ አይደለም። ከዚያም በ loop ውስጥ ያገኘነውን እናልፋለን. ስክሪፕት፡
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.###
ይህ ዘዴ ለሁሉም ሰው ተስማሚ እንዳልሆነ ተረድቻለሁ, ነገር ግን የጽሁፉ ዋና ግብ ሁሉንም ችግሮችዎን ከመፍታት ይልቅ እርምጃ መውሰድ ነው. እኔ እንደማስበው በጣም ትክክለኛው መፍትሔ የመነሻ ኮድን እራስዎ ማጥናት መጀመር ነው።
በአንዳንድ ሁኔታዎች, ፋይሉን ከመረመሩ በኋላ, ግምታዊውን መዋቅር ለመወሰን እና ከላይ ካሉት አገናኞች ውስጥ አንዱን መደበኛ ዘዴዎች በመጠቀም ወደነበረበት መመለስ ይችላሉ. ይህ በጣም ትክክል ይሆናል እና ጥቂት ችግሮችን ያስከትላል.
ምንጭ: hab.com