Index: src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java --- src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java 2011-10-17 14:23:22.000000000 +0800 +++ src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java 2011-10-17 14:23:14.000000000 +0800 @@ -258,18 +258,6 @@ this.journal.add(JournalEntry.STARTED_REGION_B_CREATION); HRegion b = createDaughterRegion(this.hri_b, this.parent.flushRequester); - // Edit parent in meta. Offlines parent region and adds splita and splitb. - // TODO: This can 'fail' by timing out against .META. but the edits could - // be applied anyways over on the server. There is no way to tell for sure. - // We could try and get the edits again subsequent to their application - // whether we fail or not but that could fail too. We should probably move - // the PONR to here before the edits go in but could mean we'd abort the - // regionserver when we didn't need to; i.e. the edits did not make it in. - if (!testing) { - MetaEditor.offlineParentInMeta(server.getCatalogTracker(), - this.parent.getRegionInfo(), a.getRegionInfo(), b.getRegionInfo()); - } - // This is the point of no return. Adding subsequent edits to .META. as we // do below when we do the daughter opens adding each to .META. can fail in // various interesting ways the most interesting of which is a timeout @@ -281,7 +269,18 @@ // crash out, then they will have their references to the parent in place // still and the server shutdown fixup of .META. will point to these // regions. + // We should add PONR JournalEntry before offlineParentInMeta,so even if + // OfflineParentInMeta timeout,this will cause regionserver exit,and then + // master ServerShutdownHandler will fix daughter & avoid data loss. See ( + // HBASE-4562). this.journal.add(JournalEntry.PONR); + + // Edit parent in meta. Offlines parent region and adds splita and splitb. + if (!testing) { + MetaEditor.offlineParentInMeta(server.getCatalogTracker(), + this.parent.getRegionInfo(), a.getRegionInfo(), b.getRegionInfo()); + } + // Open daughters in parallel. DaughterOpener aOpener = new DaughterOpener(server, services, a); DaughterOpener bOpener = new DaughterOpener(server, services, b);