在AEM 6.x中报告问题时如何调试SegmentNotFoundException

本文可帮助您了解在AEM 6.x中报告问题时如何通过恢复到区段存储的最后一个已知良好修订来调试SegmentNotFoundException。

描述 description

环境

Experience Manager6.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

要解决的步骤

有两种方法可以修复问题并删除存储库中的不一致内容

还原到区段存储的最后一个已知良好修订。

首先,使用橡木运行工具,它是一个可运行的jar[ 1] 其中包含您进行简单Oak安装和执行Oak相关操作所需的一切。

oak-run的检查运行模式可用于确定区段存储的最后一个已知良好修订。  这可用于手动将损坏的区段存储恢复为其最新的良好修订。

注意:此过程会将系统中的数据回滚到之前的时间点。  如果您希望避免丢失系统中的更改,则可以尝试下面的选项B。

要执行检查和恢复:

  1. https://mvnrepository.com/artifact/org.apache.jackrabbit/oak-run 下载与您的 oak 核心版本相匹配的 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运行检查无法找到良好修订版本的情况下,我们会在运行检查命令时获得“ConsistencyChecker — 未找到良好修订版本”。

当一致性检查中遇到“ConsistencyChecker — 未找到良好的修订”时如何修复损坏

手动删除损坏的节点。

您可以在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
    

    在外壳中运行以下两个命令来加载脚本并运行它:

    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脚本无法找到任何损坏的节点。  在这些情况下,您可以改用以下命令,它将读取遍历期间遇到的每个二进制文件的前1024个字节(请注意,此命令会较慢,并且仅应在上述命令未返回预期结果时使用):

    code language-none
    countNodes(session.workingNode,true)
    
  3. 使用rmNodes.groovy删除最后一个命令输出中列出的所有已识别的损坏节点。使用以下命令加载oak-run控制台shell:

    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及更高版本时,请设置 — 读写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 ,这意味着该命令删除了此损坏路径。 通过在这些路径上重新运行rmNode命令,确保删除这些找到的三个损坏路径。 下次运行应该返回false。
    如果您看到存储库中仍然存在相同的路径,则使用 oak-run jar的补丁版本,即oak-run-1.2.18-NPR-17596. 此版本的jar在压缩时跳过不可读的二进制文件,将它们替换为0字节二进制文件并记录异常和syserr的路径。 随后,生成的压缩存储库应该会通过oak-run检查和节点计数脚本,您还应该能够使用未打补丁的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表示区段不再存在,尽管显然有人尝试仍访问该区段。 这大致有三个不同的根本原因:区段已通过手动干预删除(例如rm -rf /),区段已通过修订垃圾收藏集删除,或者由于代码中的一些错误无法找到该区段。

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