AEM 6.x で問題が報告された場合に SegmentNotFoundException をデバッグする方法

この記事では、セグメントストアの整合性のある最も新しいリビジョンに戻すことで、AEM 6.x で問題が報告された際に SegmentNotFoundException をデバッグする方法を説明します。

説明 description

環境

Experience Manager 6.x

問題/症状

エラーログに、次の例のように SegmentNotFound 例外が表示されます。

org.apache.jackrabbit.oak.segment.SegmentNotFoundException: Segment d2c720c4-c146-4ab1-ac37-542aad93c33f not found at

org.apache.jackrabbit.oak.segment.file.FileStore$8.call(FileStore.java:602) at

org.apache.jackrabbit.oak.segment.file.FileStore$8.call(FileStore.java:542) at

org.apache.jackrabbit.oak.segment.SegmentCache.getSegment(SegmentCache.java:95) at

org.apache.jackrabbit.oak.segment.file.FileStore.readSegment(FileStore.java:542) at

org.apache.jackrabbit.oak.segment.SegmentId.getSegment(SegmentId.java:125) at

org.apache.jackrabbit.oak.segment.Record.getSegment(Record.java:70) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:424) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:433) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:391) at

org.apache.jackrabbit.oak.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:608) at

org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148) at

org.apache.jackrabbit.oak.segment.MapRecord$3.childNodeChanged(MapRecord.java:442) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:490) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:433) at

org.apache.jackrabbit.oak.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:608) at

org.apache.jackrabbit.oak.spi.commit.EditorDiff.process(EditorDiff.java:52) at

org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.updateIndex(AsyncIndexUpdate.java:695) at

org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.runWhenPermitted(AsyncIndexUpdate.java:543) at

org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.run(AsyncIndexUpdate.java:402) at

org.apache.sling.commons.scheduler.impl.QuartzJobExecutor.execute(QuartzJobExecutor.java:118) at

org.quartz.core.JobRunShell.run(JobRunShell.java:202) at

java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at

java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at

java.lang.Thread.run(Thread.java:745)

解決策 resolution

解決する手順

問題を修正してリポジトリの不整合を削除する方法は 2 つあります

セグメントストアを整合性のある最も新しいリビジョンに戻す

まず、  oak run tool を使用します。これは実行可能な jar[ 1] であり、簡単なOakのインストールと oak 関連の操作の実行に必要なすべてを含んでいます。

oak-run の check run モードを使用すると、セグメントストアの整合性のある最も新しいリビジョンを確認できます。  このリビジョンを使用して、破損しているセグメントストアを整合性のある最も新しいリビジョンに手動で戻すことができます。

注意:この操作を実行すると、システム内のデータが過去の時点にロールバックされます。  システムの変更が失われないようにするには、代わりに以下のオプション B を試してください。

check と復元を実行するには:

  1. 使用している Oak コアバージョンに合ったバージョンの oak-run を、https://mvnrepository.com/artifact/org.apache.jackrabbit/oak-run からダウンロードします。

  2. 破損しているセグメントストアを整合性のある最も新しい状態に戻すには、CQ の作業ディレクトリ(crx-quickstartfolder が含まれているディレクトリ)に変更し、内のすべてのファイルをバックアップします。/crx-quickstart/repository/segmentstore/.

  3. 整合性チェックを実行します。

    java -Xmx6000m -jar oak-run-*.jar check —bin=-1 /path/to/crx-quickstart/repository/segmentstore

    これは、リビジョンを遡って、整合性のあるリビジョンを検出します。

    次のようなメッセージを探します。

    code language-none
    main INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Found latest good revision afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880
    
  4. を編集して、リポジトリをこのリビジョンに戻します。/crx-quickstart/repository/segmentstore/journal.logを指定し、整合性のある最も新しいリビジョンを含む行より後のすべての行を削除します。

  5. すべて削除します。/crx-quickstart/repository/segmentstore/*.bak ファイル。

  6. 次のコマンドを使用して、チェックポイントのクリーンアップを実行し、孤立したチェックポイントを削除します。

    code language-none
    java -Xmx6000m -jar oak-run-*.jar checkpoints /path/to/crx-quickstart/repository/segmentstore rm-unreferenced
    
  7. 最後に、リポジトリを圧縮します。

    java -Xmx6000m -jar oak-run-*.jar compact /path/to/crx-quickstart/repository/segmentstore/

oak の実行チェックで適切なリビジョンが見つからず、check コマンドの実行中に「ConsistencyChecker - No good revision found」が表示される場合があります。

整合性チェックで「ConsistencyChecker - No good revision found」が発生した場合の破損の修正方法

破損しているノードを手動で削除します。

AEM、FileDatastore が設定されていない TarMK の設定、バイナリが破損している状況では、次の操作を実行できます。

注意 :以下の手順は、上級ユーザーを対象としています。  破損しているノードを削除するときは、それがシステムノード(/home、/jcr:system など)でないことを確認する必要があります。  システムノードの場合は、復元できることを確認する必要があります。  ここに記載されている手順について不明な点がある場合は、AEM カスタマーケアチームにお問い合わせください。

  1. AEM を停止します。

  2. Oak実行コンソールを使用し、childCount groovy スクリプトを読み込んで、セグメントストア内の破損しているノードを特定します。

    oak-run コンソールシェルを読み込みます。

    code language-none
    java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
    

    次の 2 つのコマンドをシェルで実行してスクリプトを読み込み、実行します。

    code language-none
    :load https://gist.githubusercontent.com/stillalex/e7067bcb86c89bef66c8/raw/d7a5a9b839c3bb0ae5840252022f871fd38374d3/childCount.groovy
    countNodes(session.workingNode)
    

    次のように、破損しているノードのパスが出力に示されます。

    code language-none
    21:21:42.029 main ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 63ae05a4-b506-445c-baa2-cfa1b13b6e2f. Creation date delta is 3 ms.
    warning unable to read node /content/dam/test.txt/jcr:content/renditions/original/jcr:content
    

    場合によっては、問題がバイナリプロパティに関係していて、childCount groovy スクリプトを使用しても破損しているノードを見つけることができないことがあります。  その場合は、代わりに次のコマンドを使用します。このコマンドを使用すると、走査中に検出されたすべてのバイナリの最初の 1,024 バイトが読み取られます(このコマンドは低速なので、上記のコマンドを実行しても期待される結果が返さない場合にのみ使用してください)。

    code language-none
    countNodes(session.workingNode,true)
    
  3. rmNodes.groovy を使用して、最後のコマンドの出力に含まれる特定された破損しているノードをすべて削除します。
    次のコマンドを使用して、oak-run コンソールシェルを読み込みます。

    code language-none
    java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
    

    groovy スクリプトを読み込みます。

    code language-none
    :load
    https://gist.githubusercontent.com/stillalex/43c49af065e3dd1fd5bf/raw/9e726a59f75b46e7b474f7ac763b0888d5a3f0c3/rmNode.groovy
    

    rmNode コマンドを実行して、破損しているノードを削除します。/path/to/corrupt/node を、削除する必要がある破損しているノードのパスに置き換えます。

    code language-none
    rmNode(session, "/path/to/corrupt/node")
    

    ここで、破損しているノードのパスとは、手順 2 で取得したパスです(例:「/content/dam/test.txt/jcr:content/renditions/original/jcr:content/」)。

    メモ:oak-run.jar バージョン 1.6.13 以上を使用していて、次のようなエラーになった場合は、—read-write JVM パラメーターを設定します。

    code language-none
    / rmNode(session,"/path/to/corrupt/node")    Removing node /path/to/corrupt/node    ERROR java.lang.UnsupportedOperationException:    Cannot write to read-only store    at org.apache.jackrabbit.oak.segment.SegmentWriterBuilder$1.execute (SegmentWriterBuilder.java:171)    at org.apache.jackrabbit.oak.segment.SegmentWriter.writeNode (SegmentWriter.java:318)    at org.apache.jackrabbit.oak.segment.SegmentNodeBuilder.getNodeState (SegmentNodeBuilder.java:111)    at org.apache.jackrabbit.oak.segment.SegmentNodeStore$Commit.init (SegmentNodeStore.java:581)    at org.apache.jackrabbit.oak.segment.SegmentNodeStore.merge (SegmentNodeStore.java:333)    at org.apache.jackrabbit.oak.spi.state.NodeStore$merge.call (Unknown Source)    at groovysh_evaluate.rmNode (groovysh_evaluate:11)
    
  4. 手順 2 で見つかったすべてのノードについて、手順 3 を繰り返します

    上記の rmNode コマンドを破損しているパスに対して実行すると、true が返されます。これは、コマンドによってパスが削除されたことを意味します。 これらの見つかった 3 つの破損しているパスに対して rmNode コマンドを再実行して、これらのパスを削除します。 次に実行すると、false が返されます。
    リポジトリに同じパスがまだ存在する場合は、 パッチが適用されたバージョンの oak-run jar (oak-run-1.2.18-NPR-17596)を使用します。 このバージョンの jar は、圧縮時に読み取り不可能なバイナリをスキップし、0 バイトのバイナリに置き換えて、例外とパスを syserr に記録します。 結果として得られた圧縮リポジトリは、oak-run check とノード数スクリプトに合格します。また、パッチの適用されていない oak-run を使用してリポジトリを再度圧縮できるようになります。

  5. 次のコマンドを使用してチェックポイントをリストして、チェックポイントをクリーンアップします。複数のチェックポイントがある場合は、それらをクリーンアップします。

    code language-none
    nohup java -Xmx4096m -jar oak-run-1.2.18.jar checkpoints /app/AEM6/author/crx-quickstart/repository/segmentstore rm-allnohup.out
    
  6. オフライン圧縮を実行します。 オフライン圧縮の実行方法がわからない場合は、​ こちら ​ を参照してください。

  7. サーバーを起動し、インデックスの作成が完了するまで待ちます。

原因

エラーログの SegmentNotFoundException は、誰かが引き続きアクセスしようとしているにもかかわらず、セグメントが存在しないことを意味します。 これには、大きく 3 つの異なる根本原因があります。手動の介入(rm -rf /など)によってセグメントが削除されたか、リビジョンのガベージコレクションによってセグメントが削除されたか、コードのバグが原因でセグメントが見つからないということです。

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f