كيف قمت بإصلاح جدول من postgres

أكتب هذا المنشور بخصوص خطأ في جزء مفقود في جدول postgres كان يتسبب في فشل النسخ الاحتياطي اليومي الخاص بي. تمكنت من حل المشكلة وأرغب في عرض الطريقة التي استخدمتها في حال كانت مفيدة لشخص آخر يواجه هذه المشكلة. لا يُعد هذا بأي حال من الأحوال دليلًا أو تعليمات احترافية لحل أخطاء أجزاء postgres المفقودة بشكل صحيح لأنني لست خبيرًا وقمت بذلك دون معرفة كبيرة، لكنه نجح في النهاية.
الخطأ الذي كنت أتلقاه أثناء النسخ الاحتياطي:

 pg_dump: error: Dumping the contents of table "stylesheet_cache" failed: PQgetResult() failed.
 pg_dump: error: Error message from server: ERROR:  missing chunk number 0 for toast value 1903804 in pg_toast_22663
 pg_dump: error: The command was: COPY public.stylesheet_cache (id, target, digest, content, created_at, updated_at, theme_id, source_map) TO stdout;

إذًا، كانت المشكلة في جدول stylesheet_cache، الخطأ: missing chunk number 0 for toast value 1903804 in pg_toast_22663.
أنا أستخدم Discourse في Docker، لذا إليك ما فعلته:

ssh into the server
cd /path/to/discourse
./launcher rebuild app
su postgres -c "psql discourse"

بمجرد دخولي إلى postgres، حاولت إعادة فهرسة الجدول على أمل أن يحل ذلك المشكلة.

discourse=# select reltoastrelid::regclass from pg_class where relname = 'stylesheet_cache';
      reltoastrelid
-------------------------
 pg_toast.pg_toast_18396
(1 row)
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_18396;
VACUUM analyze stylesheet_cache;

حاولت إجراء النسخ الاحتياطي مرة أخرى، وفشل، لذلك اضطررت إلى مواصلة البحث عن التلف.
حسبت العدد الإجمالي للصفوف في جدولي باستخدام:

select count(*) from stylesheet_cache;

حصلت على عدد 2260 صفًا.
ذهبت للبحث عن الصف المحدد الذي به تلف وحذفه، افترضت بطريقة ما أن stylesheet_cache ليس شيئًا يمكن أن يكسر قاعدة بياناتي بأكملها حقًا. كما ذكرت، أنا لست خبيرًا، لذلك ربما قمت بخطوة جريئة جدًا، لذا كن حذرًا عند القيام بذلك لأنك قد تتسبب في تلف قاعدة بياناتك.
استخدمت استعلامات LIMIT و OFFSET للعثور على الصفوف التالفة.

select * from stylesheet_cache order by id limit 100 offset 0;

لعبت بالـ offset والـ limit حتى حصلت على خطأ Missing chunk… ثم قمت بتضييق النطاق إلى LIMIT 1 و offset الصف الذي كان تالفًا. في حالتي، كان هناك 5 صفوف تالفة.
يمكنك استخدام شريط نصي للعثور على الصف بجهد أقل، لقد اتبعت الطريقة اليدوية التي استغرقت بعض الوقت ولكن يمكنك استخدام هذا:

#!/bin/sh
j=0
while [ $j -lt 2260 ]
do
  psql -U postgres -d discourse -c "SELECT * FROM stylesheet_cache LIMIT 1 offset $j" >/dev/null || echo $j
  j=$(($j+1))
done

ذهبت للعثور على معرف الصف التالف باستخدام الأمر التالي:

select id from stylesheet_cache order by id limit 1 offset 450;

id

----

11498

إذًا، كان معرف صفي التالف هو 11498.
حذفت الصف باستخدام

delete from stylesheet_cache where id = 11498;

بعد حذف الصفوف التالفة، ذهبت لإعادة الفهرسة مرة أخرى.

REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_40948;
VACUUM analyze stylesheet_cache;

وحاولت النسخ الاحتياطي مرة أخرى، هذه المرة نجح. لقد استرشدت بتعليمات استرداد postgres هذه: Postgres error: Missing chunk 0 for toast value in pg_toast · GitHub

إخلاء مسؤولية: هذا ليس رأيًا خبيرًا، لذا توخ الحذر إذا كانت لديك أخطاء تلف مماثلة في الأجزاء المفقودة وتحاول إصلاحها.

3 إعجابات