منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

مان توهان سان حصيداري ڪرڻ چاهيندس پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ جو منهنجو پهريون ڪامياب تجربو مڪمل ڪارڪردگي ڏانهن. مان اڌ سال اڳ Postgres DBMS سان واقف ٿيس؛ ان کان اڳ مون وٽ ڊيٽابيس انتظاميه ۾ ڪو به تجربو نه هو.

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

مان هڪ وڏي آئي ٽي ڪمپني ۾ نيم DevOps انجنيئر طور ڪم ڪريان ٿو. اسان جي ڪمپني تيز لوڊ سروسز لاءِ سافٽ ويئر ٺاهي ٿي، ۽ مان ڪارڪردگي، سار سنڀال ۽ لڳائڻ جو ذميوار آهيان. مون کي هڪ معياري ڪم ڏنو ويو: هڪ سرور تي ايپليڪيشن کي تازه ڪاري ڪرڻ. ايپليڪيشن Django ۾ لکيل آهي، اپڊيٽ جي دوران لڏپلاڻ ڪئي ويندي آهي (ڊيٽابيس جي جوڙجڪ ۾ تبديليون)، ۽ ان عمل کان اڳ اسين معياري pg_dump پروگرام ذريعي مڪمل ڊيٽابيس ڊمپ وٺون ٿا، صرف صورت ۾.

ڊمپ کڻڻ دوران اڻڄاتل غلطي ٿي وئي (Postgres ورجن 9.5):

pg_dump: Oumping the contents of table “ws_log_smevlog” failed: PQgetResult() failed.
pg_dump: Error message from server: ERROR: invalid page in block 4123007 of relatton base/16490/21396989
pg_dump: The command was: COPY public.ws_log_smevlog [...]
pg_dunp: [parallel archtver] a worker process dled unexpectedly

غلطي "غلط صفحو بلاڪ ۾" فائل سسٽم جي سطح تي مسئلن جو ذڪر ڪري ٿو، جيڪو تمام خراب آهي. مختلف فورمن تي ان کي ڪرڻ جي صلاح ڏني وئي مڪمل ويڪيوم اختيار سان zero_damaged_pages هن مسئلي کي حل ڪرڻ لاء. خير، اچو ته ڪوشش ڪريون ...

بحالي جي تياري

حرف! توهان جي ڊيٽابيس کي بحال ڪرڻ جي ڪنهن به ڪوشش کان پهريان پوسٽ گريس بيڪ اپ وٺڻ جي پڪ ڪريو. جيڪڏهن توهان وٽ هڪ مجازي مشين آهي، ڊيٽابيس کي روڪيو ۽ هڪ سنيپ شاٽ وٺو. جيڪڏهن سنيپ شاٽ وٺڻ ممڪن نه آهي، ڊيٽابيس کي روڪيو ۽ پوسٽ گريس ڊاريڪٽري جي مواد کي نقل ڪريو (بشمول وال فائلون) محفوظ جڳهه تي. اسان جي ڪاروبار ۾ بنيادي شيء شيون خراب ڪرڻ نه آهي. پڙهو ان.

جيئن ته ڊيٽابيس عام طور تي مون لاء ڪم ڪيو، مون پاڻ کي باقاعده ڊيٽابيس ڊمپ تائين محدود ڪيو، پر خراب ٿيل ڊيٽا سان ٽيبل کي خارج ڪيو (اختيار -T، -exclude-table = ٽيبل pg_dump ۾).

سرور جسماني هو، ان لاءِ سنيپ شاٽ وٺڻ ناممڪن هو. بيڪ اپ هٽايو ويو آهي، اچو ته اڳتي وڌو.

فائل سسٽم چيڪ ڪريو

ڊيٽابيس کي بحال ڪرڻ جي ڪوشش ڪرڻ کان پهريان، اسان کي پڪ ڪرڻ جي ضرورت آهي ته هر شي فائل سسٽم سان ترتيب ۾ آهي. ۽ غلطين جي صورت ۾، انهن کي درست ڪريو، ڇو ته ٻي صورت ۾ توهان صرف شيون خراب ڪري سگهو ٿا.

منهنجي حالت ۾، ڊيٽابيس سان گڏ فائيل سسٽم نصب ڪيو ويو "/srv" ۽ قسم ext4 هو.

ڊيٽابيس کي روڪڻ: systemctl اسٽاپ [ايميل محفوظ ٿيل] ۽ چيڪ ڪريو ته فائل سسٽم ڪنهن جي استعمال ۾ نه آهي ۽ ڪمانڊ استعمال ڪندي ان مائونٽ ٿي سگهي ٿو لسٽ:
lsof +D /srv

مون کي پڻ ريڊيس ڊيٽابيس کي روڪڻو هو، ڇاڪاڻ ته اهو پڻ استعمال ڪري رهيو هو "/srv". اڳتي هلي مون اُن مائونٽ ڪيو / ايس آر وي (umount).

فائل سسٽم کي استعمال ڪندي چيڪ ڪيو ويو e2fsck سوئچ سان -f (چيڪ ڪرڻ لاءِ زور ڀريو جيتوڻيڪ فائل سسٽم کي صاف نشان لڳايو ويو آهي):

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

اڳيون، افاديت استعمال ڪندي dumpe2fs (sudo dumpe2fs /dev/mapper/gu2—sys-srv | grep چيڪ ڪيو) توهان تصديق ڪري سگهو ٿا ته چيڪ اصل ۾ ڪيو ويو هو:

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

e2fsck چوي ٿو ته ext4 فائل سسٽم جي سطح تي ڪو به مسئلو نه مليو، جنهن جو مطلب اهو آهي ته توهان ڊيٽابيس کي بحال ڪرڻ جي ڪوشش جاري رکي سگهو ٿا، يا واپسي ڏانهن واپس وڃو. خالي خالي (يقينا، توهان کي فائل سسٽم کي واپس آڻڻ ۽ ڊيٽابيس کي شروع ڪرڻ جي ضرورت آهي).

جيڪڏهن توهان وٽ فزيڪل سرور آهي، پڪ ڪريو ته ڊسڪ جي حالت چيڪ ڪريو (ذريعي smartctl -a /dev/XXX) يا RAID ڪنٽرولر کي پڪ ڪرڻ لاء ته مسئلو هارڊويئر سطح تي نه آهي. منهنجي حالت ۾، RAID "هارڊويئر" نڪتو، تنهنڪري مون مقامي منتظم کي RAID جي صورتحال کي جانچڻ لاء چيو (سرور مون کان ڪيترائي سئو ڪلوميٽر پري هو). هن چيو ته ڪا به نقص نه هئي، جنهن جو مطلب آهي ته اسان بحالي جي شروعات ضرور ڪري سگهون ٿا.

ڪوشش 1: zero_damaged_pages

اسان ڊيٽابيس سان psql ذريعي ڳنڍيون ٿا هڪ اڪائونٽ سان جنهن وٽ سپر يوزر جا حق آهن. اسان کي هڪ سپر استعمال ڪندڙ جي ضرورت آهي، ڇاڪاڻ ته ... اختيار zero_damaged_pages صرف هو تبديل ڪري سگهي ٿو. منهنجي صورت ۾ اهو پوسٽ گريس آهي:

psql -h 127.0.0.1 -U postgres -s [database_name]

اختيار zero_damaged_pages پڙهڻ جي غلطين کي نظرانداز ڪرڻ جي ضرورت آهي (پوسٽ گريسپرو ويب سائيٽ تان):

جڏهن PostgreSQL هڪ خراب صفحي جي هيڊر کي ڳولي ٿو، اهو عام طور تي هڪ غلطي جي رپورٽ ڪري ٿو ۽ موجوده ٽرانزيڪشن کي ختم ڪري ٿو. جيڪڏهن zero_damaged_pages فعال آهي، سسٽم بدران هڪ ڊيڄاريندڙ جاري ڪري ٿو، ميموري ۾ خراب ٿيل صفحي کي صفر ڪري ٿو، ۽ پروسيسنگ جاري رکي ٿو. اهو رويو ڊيٽا کي تباهه ڪري ٿو، يعني خراب ٿيل صفحي ۾ سڀئي قطارون.

اسان اختيار کي چالو ڪيو ۽ جدولن جي مڪمل خلا ڪرڻ جي ڪوشش ڪريو:

VACUUM FULL VERBOSE

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)
بدقسمتي سان، بدقسمتي سان.

اسان کي هڪ اهڙي غلطي ملي آهي:

INFO: vacuuming "“public.ws_log_smevlog”
WARNING: invalid page in block 4123007 of relation base/16400/21396989; zeroing out page
ERROR: unexpected chunk number 573 (expected 565) for toast value 21648541 in pg_toast_106070

pg_toast - Poetgres ۾ "ڊگهي ڊيٽا" کي محفوظ ڪرڻ لاء هڪ ميکانيزم جيڪڏهن اهو هڪ صفحي تي نه ٿو اچي (ڊفالٽ طور 8kb).

ڪوشش 2: reindex

گوگل کان پهرين صلاح مدد نه ڪئي. ڪجھ منٽن جي ڳولا کان پوء، مون کي ٻيو ٽپ مليو - ٺاهڻ لاء reindex خراب ٿيل ٽيبل. مون ڪيترن ئي هنڌن تي اهو مشورو ڏٺو، پر اهو اعتماد نه ڪيو. اچو ته ٻيهر ترتيب ڏيو:

reindex table ws_log_smevlog

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

reindex بغير مسئلن جي مڪمل.

بهرحال، اهو مدد نه ڪيو، ويڪيوم مڪمل ساڳي غلطي سان تباهه ٿي ويو. جيئن ته مون کي ناڪامين لاء استعمال ڪيو ويو آهي، مون انٽرنيٽ تي مشوري لاء وڌيڪ ڏسڻ شروع ڪيو ۽ هڪ بلڪه دلچسپ ۾ آيو مضمون.

ڪوشش 3: چونڊيو، حد، آفسٽ

مٿي ڏنل مضمون ۾ جدول جي قطار کي قطار ۾ ڏسڻ ۽ مشڪلاتي ڊيٽا کي ختم ڪرڻ جي صلاح ڏني وئي. پهرين اسان کي سڀني لائينن کي ڏسڻ جي ضرورت آهي:

for ((i=0; i<"Number_of_rows_in_nodes"; i++ )); do psql -U "Username" "Database Name" -c "SELECT * FROM nodes LIMIT 1 offset $i" >/dev/null || echo $i; done

منهنجي حالت ۾، ٽيبل تي مشتمل آهي 1 628 991 لائنون! چڱيءَ طرح سنڀال ڪرڻ ضروري هو ڊيٽا ورهاڱي، پر هي هڪ الڳ بحث جو موضوع آهي. اهو ڇنڇر هو، مون هن حڪم کي tmux ۾ هلائي ڇڏيو ۽ بستري تي ويس:

for ((i=0; i<1628991; i++ )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog LIMIT 1 offset $i" >/dev/null || echo $i; done

صبح جو مون فيصلو ڪيو ته چيڪ ڪريو ته شيون ڪيئن ٿي رهيون آهن. منهنجي تعجب ۾، مون دريافت ڪيو ته 20 ڪلاڪن کان پوء، ڊيٽا جو صرف 2٪ اسڪين ڪيو ويو هو! مون کي 50 ڏينهن انتظار ڪرڻ نه چاهيو. ٻي مڪمل ناڪامي.

پر مون نه هارايو. مان حيران ٿي ويس ته اسڪيننگ ايتري دير ڇو ورتي. دستاويزن مان (ٻيهر پوسٽ گريسپرو تي) مون کي معلوم ٿيو:

OFFSET وضاحت ڪري ٿو ته قطارن جي مخصوص تعداد کي ڇڏڻ کان پهريان قطارن کي ٻاھر ڪڍڻ شروع ڪريو.
جيڪڏهن ٻئي OFFSET ۽ LIMIT بيان ڪيا ويا آهن، سسٽم پهريون ڀيرو OFFSET قطارن کي ڇڏي ٿو ۽ پوء LIMIT رڪاوٽ لاء قطارون ڳڻڻ شروع ڪري ٿو.

جڏهن LIMIT استعمال ڪيو وڃي، اهو ضروري آهي ته هڪ ORDER BY شق پڻ استعمال ڪيو وڃي ته جيئن نتيجن جون قطارون هڪ مخصوص ترتيب ۾ واپس اچن. ٻي صورت ۾، قطار جا غير متوقع سبسٽس واپس ڪيا ويندا.

ظاهر آهي، مٿي ڏنل حڪم غلط هو: پهرين، نه هو طرفان آرڊر، نتيجو غلط ٿي سگهي ٿو. ٻيو، پوسٽ گريس کي پهرين اسڪين ڪرڻي هئي ۽ OFFSET قطار کي ڇڏي ڏيو، ۽ وڌڻ سان آفس پيداوار اڃا به گهٽجي ويندي.

ڪوشش 4: ٽيڪسٽ فارم ۾ ڊمپ وٺو

ان کان پوء هڪ شاندار خيال منهنجي ذهن ۾ آيو: ٽيڪسٽ فارم ۾ ڊمپ وٺو ۽ آخري رڪارڊ ٿيل لائن جو تجزيو ڪريو.

پر پهرين، اچو ته ٽيبل جي جوڙجڪ تي هڪ نظر رکون. ws_log_smevlog:

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

اسان جي صورت ۾ اسان وٽ هڪ ڪالم آهي ”آئي ڊي“، جنهن ۾ قطار جي منفرد سڃاڻپ ڪندڙ (ڪائونٽر) شامل آهي. منصوبو هن طرح هو:

  1. اسان ٽيڪسٽ فارم ۾ ڊمپ وٺڻ شروع ڪيو (sql حڪمن جي صورت ۾)
  2. وقت جي هڪ خاص نقطي تي، ڊمپ کي خرابي جي ڪري روڪيو ويندو، پر ٽيڪسٽ فائل اڃا تائين ڊسڪ تي محفوظ ڪيو ويندو.
  3. اسان ٽيڪسٽ فائل جي پڇاڙيءَ ۾ ڏسون ٿا، ان ڪري اسان کي آخري لائين جو سڃاڻپ ڪندڙ (id) ملي ٿو جيڪو ڪاميابيءَ سان هٽايو ويو.

مون ٽيڪسٽ فارم ۾ ڊمپ وٺڻ شروع ڪيو:

pg_dump -U my_user -d my_database -F p -t ws_log_smevlog -f ./my_dump.dump

ڊمپ، جيئن توقع ڪئي وئي، ساڳئي غلطي سان مداخلت ڪئي وئي:

pg_dump: Error message from server: ERROR: invalid page in block 4123007 of relatton base/16490/21396989

اڳتي هلي پڇ مون ڊمپ جي آخر ۾ ڏٺو (دم -5 ./my_dump.dump) دريافت ڪيو ته ڊمپ id سان لائن تي مداخلت ڪئي وئي 186 525. "تنهنڪري مسئلو id 186 526 جي قطار ۾ آهي، اهو ڀڄي ويو آهي، ۽ ختم ٿيڻ جي ضرورت آهي!" - مون سوچيو. پر، ڊيٽابيس ڏانهن سوال ڪرڻ:
«ws_log_smevlog مان * چونڊيو جتي id=186529"اهو ظاهر ٿيو ته هن لائن سان سڀ ڪجهه ٺيڪ هو ... انڊيڪس 186 - 530 سان قطارون به بغير ڪنهن مسئلن جي ڪم ڪيو. ٻيو "شاندار خيال" ناڪام ٿيو. بعد ۾ مون کي سمجھ ۾ آيو ته ائين ڇو ٿيو: جڏهن ڊيٽا کي حذف ڪرڻ ۽ تبديل ڪرڻ واري ٽيبل مان، اهي جسماني طور تي ڊاهي نه ويندا آهن، پر نشان لڳل آهن "مئل ٽوپل"، پوء اچي ٿو. خودڪار ويڪيوم ۽ نشان لڳايو انهن لائينن کي ختم ٿيل طور ۽ انهن لائينن کي ٻيهر استعمال ڪرڻ جي اجازت ڏئي ٿو. سمجھڻ لاءِ، جيڪڏھن جدول ۾ ڊيٽا تبديل ٿي وڃي ۽ آٽو ويڪيوم کي فعال ڪيو وڃي، ته پوءِ ان کي ترتيب وار ذخيرو نه ڪيو ويندو.

ڪوشش 5: SELECT, FROM, WHERE id=

ناڪاميون اسان کي مضبوط ڪن ٿيون. توهان کي ڪڏهن به نه ڇڏڻ گهرجي، توهان کي آخر تائين وڃڻ گهرجي ۽ پنهنجي پاڻ ۽ توهان جي صلاحيتن تي يقين رکڻ گهرجي. تنهن ڪري مون هڪ ٻيو اختيار آزمائي ڪرڻ جو فيصلو ڪيو: صرف ڊيٽابيس ۾ سڀني رڪارڊن کي هڪ هڪ ڪري ڏسو. منهنجي ٽيبل جي جوڙجڪ کي ڄاڻڻ (مٿي ڏسو)، اسان وٽ هڪ id فيلڊ آهي جيڪو منفرد آهي (پرائمري ڪي). اسان وٽ ٽيبل ۾ 1 قطارون آهن ۽ id ترتيب ۾ آهن، جنهن جو مطلب آهي ته اسان صرف انهن مان هڪ هڪ ذريعي وڃي سگهون ٿا:

for ((i=1; i<1628991; i=$((i+1)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done

جيڪڏهن ڪو نه سمجهي، حڪم هن ريت ڪم ڪري ٿو: اهو قطار جي قطار کي اسڪين ڪري ٿو ۽ stdout ڏانهن موڪلي ٿو / خوف / خفيه، پر جيڪڏهن SELECT ڪمانڊ ناڪام ٿئي ٿي، ته پوءِ غلطي جو متن ڇپبو آهي (stderr ڪنسول ڏانهن موڪليو ويو آهي) ۽ هڪ لڪير جنهن ۾ غلطي آهي پرنٽ ڪئي وئي آهي (مهرباني ڪري ||، جنهن جو مطلب آهي ته چونڊ ۾ مسئلا هئا (ڪمانڊ جو واپسي ڪوڊ) نه آهي 0)).

مان خوش قسمت هوس، مون کي فيلڊ تي انڊيڪس ٺاهيا هئا id:

منهنجو پهريون تجربو هڪ ناڪامي کان پوء پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ (رليٽٽن بيس / 4123007 جي بلاڪ 16490 ۾ غلط صفحو)

هن جو مطلب آهي ته مطلوب id سان هڪ لائن ڳولڻ ۾ گهڻو وقت نه وٺڻ گهرجي. نظريي ۾ اهو ڪم ڪرڻ گهرجي. خير، اچو ته ڪمانڊ اندر هلون ٽمڪس ۽ اچو ته سمهون.

صبح جو مون کي معلوم ٿيو ته اٽڪل 90 داخلائون ڏٺيون ويون، جيڪو صرف 000 سيڪڙو کان مٿي آهي. هڪ بهترين نتيجو جڏهن اڳئين طريقي جي مقابلي ۾ (5٪)! پر مون 2 ڏينهن انتظار ڪرڻ نه چاهيو...

ڪوشش 6: SELECT, FROM, WHERE id >= ۽ id <

ڪسٽمر وٽ ڊيٽابيس لاءِ وقف ڪيل هڪ بهترين سرور هو: ڊبل پروسيسر Intel Xeon E5-2697 v2اسان جي جڳھ ۾ 48 سٽون آھن! سرور تي لوڊ اوسط هو؛ اسان بغير ڪنهن پريشاني جي اٽڪل 20 موضوع ڊائون لوڊ ڪري سگهون ٿا. اتي پڻ ڪافي رام هئي: جيترو 384 گيگا بائيٽ!

تنهن ڪري، حڪم کي متوازي ٿيڻ جي ضرورت آهي:

for ((i=1; i<1628991; i=$((i+1)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done

هتي اهو ممڪن هو ته هڪ خوبصورت ۽ خوبصورت اسڪرپٽ لکڻ، پر مون تيز ترين متوازي طريقي جو طريقو چونڊيو آهي: دستي طور تي 0-1628991 جي حد کي 100 رڪارڊ جي وقفن ۾ ورهايو ۽ الڳ الڳ فارم جي 000 حڪمن کي هلائڻ:

for ((i=N; i<M; i=$((i+1)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done

پر اهو سڀ ڪجهه ناهي. نظريي ۾، ڊيٽابيس سان ڳنڍڻ پڻ ڪجهه وقت ۽ سسٽم وسيلن جي ضرورت آهي. 1 سان ڳنڍڻ تمام هوشيار نه هو، توهان متفق آهيو. تنهن ڪري، اچو ته ٻيهر حاصل ڪريون 628 قطارون هڪ بدران هڪ ڪنيڪشن تي. نتيجي طور، ٽيم ھن ۾ تبديل ٿي وئي:

for ((i=N; i<M; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done

tmux سيشن ۾ 16 ونڊوز کوليو ۽ حڪم جاري ڪريو:

1) for ((i=0; i<100000; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
2) for ((i=100000; i<200000; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
…
15) for ((i=1400000; i<1500000; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
16) for ((i=1500000; i<1628991; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done

هڪ ڏينهن بعد مون کي پهريون نتيجو مليو! يعني (قيمت XXX ۽ ZZZ هاڻي محفوظ نه آهن):

ERROR:  missing chunk number 0 for toast value 37837571 in pg_toast_106070
829000
ERROR:  missing chunk number 0 for toast value XXX in pg_toast_106070
829000
ERROR:  missing chunk number 0 for toast value ZZZ in pg_toast_106070
146000

هن جو مطلب آهي ته ٽن لائينن ۾ هڪ غلطي آهي. پهرين ۽ ٻئي مسئلي واري رڪارڊ جي سڃاڻپ 829 ۽ 000 جي وچ ۾ هئي، ٽئين جي سڃاڻپ 830 ۽ 000 جي وچ ۾ هئي. اڳتي هلي، اسان کي صرف مشڪلاتي رڪارڊ جي صحيح سڃاڻپ جي قيمت ڳولڻي هئي. هن کي ڪرڻ لاء، اسان 146 جي قدم سان مشڪلاتي رڪارڊ سان اسان جي حد جي ذريعي ڏسو ۽ سڃاڻپ جي سڃاڻپ:

for ((i=829000; i<830000; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
829417
ERROR:  unexpected chunk number 2 (expected 0) for toast value 37837843 in pg_toast_106070
829449
for ((i=146000; i<147000; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
829417
ERROR:  unexpected chunk number ZZZ (expected 0) for toast value XXX in pg_toast_106070
146911

خوشيءَ جو خاتمو

اسان کي مشڪلاتي لائنون مليون آهن. اسان psql ذريعي ڊيٽابيس ۾ وڃون ٿا ۽ انهن کي حذف ڪرڻ جي ڪوشش ڪريو:

my_database=# delete from ws_log_smevlog where id=829417;
DELETE 1
my_database=# delete from ws_log_smevlog where id=829449;
DELETE 1
my_database=# delete from ws_log_smevlog where id=146911;
DELETE 1

منهنجي تعجب ۾، داخلا بغير ڪنهن به مسئلي کان سواء بغير ختم ٿي ويا zero_damaged_pages.

پوءِ مون ڊيٽابيس سان ڳنڍيو، ڪيو ويڪيوم مڪمل (منهنجو خيال آهي ته اهو ڪرڻ ضروري نه هو)، ۽ آخرڪار مون ڪاميابي سان بيڪ اپ کي استعمال ڪندي هٽايو pg_dump. ڊمپ بغير ڪنهن غلطي جي ورتو ويو! مسئلو اهڙي بيوقوف طريقي سان حل ڪيو ويو. خوشي جي ڪا به حد نه هئي، ڪيترين ئي ناڪامين کان پوءِ اسان هڪ حل ڳولڻ ۾ ڪامياب ٿي ويا آهيون!

اعتراف ۽ نتيجو

اهو ڪيئن آهي منهنجو پهريون تجربو هڪ حقيقي پوسٽ گريس ڊيٽابيس کي بحال ڪرڻ جو نڪتو. مون کي اهو تجربو هڪ ڊگهي وقت تائين ياد رهندو.

۽ آخر ۾، مان چوڻ چاهيان ٿو پوسٽ گريس پرو جي مهرباني جو توهان دستاويزن کي روسي ۾ ترجمو ڪرڻ ۽ ان لاءِ مڪمل طور تي مفت آن لائن ڪورس، جنهن مسئلي جي تجزيي دوران تمام گهڻي مدد ڪئي.

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

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