非同期タスクの処理で「Caused by: org.postgresql.util.PSQLException: ERROR: missing chunk number XXXX for toast value XXXX in pg_toast_XXXX」というエラーが発生します。

 
【発生条件】
PostgreSQL の TOAST テーブルのデータ破損に関連して発生します。

【原因】
ウィルス対策ソフトが PostgreSQL で利用するディレクトリを監視対象としている場合に、発生することがあります。

【回避方法】
ウィルス対策ソフトが PostgreSQL で利用するディレクトリを監視対象としている場合は、監視対象から除外していただくことで、回避することができます。
または、該当テーブルの REINDEX と VACUUM ANALYZE を定期実行することで、回避することができます。


【対応方法】
非同期タスクの処理で該当のエラーがすでに発生してしまった場合は、該当テーブルの REINDEX と VACUUM ANALYZE、および破損したデータを特定して削除することでエラーを解消できます。
その上で上記の回避方法により、以降のエラー発生を回避することができます。

以下に、該当テーブルの REINDEX と VACUUM ANALYZE、および破損したデータを特定して削除する手順を記載します。


1. システムデータベースのバックアップを取得します。

2. REINDEX を行います。

 (1) 対象のtoastテーブルを特定します。

  エラーメッセージから対象のtoastテーブルを特定します
  【エラーメッセージ例】
  ===================
  org.postgresql.util.PSQLException: ERROR: missing chunk number 0 for toast value 2859633 in pg_toast_112208
  ===================
  上記メッセージの場合、「pg_toast_112208」が対象のtoastテーブルとなります。

 (2) toastテーブルのリレーションテーブルを特定します。

  【PSQL例】
  ===================
  => select 112208::regclass; 
        regclass
  --------------------
   im_async_task_info
  ===================
  上記例では「pg_toast_112208」の「112208」からリレーションを特定しています。

 (3) toastテーブルとリレーションテーブルをREINDEXします。

  【PSQL例】
  ===================
  =# GRANT usage ON schema pg_toast TO ユーザ;  -- pg_toastへの権限をREINDEX実行ユーザに付与(スーパーユーザが実行)
  ===================
  ===================
  => REINDEX table pg_toast.pg_toast_112208;  -- toastテーブルをREINDEX
  => REINDEX table im_async_task_info;  -- im_async_task_infoをREINDEX
  ===================

3. リレーションテーブルに対してVACUUM と ANALYZE を行います。

 【PSQL例】
 ===================
 => VACUUM ANALYZE im_async_task_info;  -- im_async_task_info を VACUUM ANALYZE
 ===================
 
 上記でエラーが発生する場合は次の手順に進みます。
 エラーがなければ完了です。

4. 破損データの特定と削除を行う
 
 (1) 2. で特定したリレーションテーブルのエラー行を特定します。
 
  下記の例の場合は1件ずつSELECTを実行してエラー発生行を特定しています。
  【PSQL例】
  ===================
  => SET client_min_messages TO notice;  --コンソールに出力するための設定
  => DO $$
  declare
    v_rec record;
  BEGIN    
    for v_rec in SELECT * FROM im_async_task_info ORDER BY message_id loop
      RAISE NOTICE '%', v_rec.message_id; 
    end loop;
  END;
  $$
  ;
  --エラーが発生した行のデータが破損している。
  ===================
 
 (2) エラー発生行のデータと、関連データを削除します。
 
  下記例では「im_async_task_info」と「im_async_task_info」に紐づく「im_async_context_info」を削除しています。
  【PSQL例】
  ===================
  => DELETE FROM im_async_context_info WHERE identifier IN (SELECT context FROM im_async_task_info WHERE message_id = 'XXXXXX');
  => DELETE FROM im_async_task_info where message_id ='XXXXXX';
  ===================
 
 (3) エラーが解消されたか確認します。
  
  4-(1)を再度実行し、エラー行がないことを確認します。
  エラー行がある場合は 4-(2)の通り削除を行います。

5. リレーションテーブルに対してVACUUMFULLを行います。

 【PSQL例】
 ===================
 => VACUUMFULL im_async_task_info;  -- im_async_task_info を VACUUMFULL
 ===================

以上で完了です。

-- 対象 ------------------------------------------------------------------------ 
iAP/Accel Platform/全アップデート
--------------------------------------------------------------------------------


FAQID:1163
この記事は役に立ちましたか?
0人中0人がこの記事が役に立ったと言っています
Powered by Zendesk