[ 
https://issues.apache.org/jira/browse/HBASE-29111?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Duo Zhang resolved HBASE-29111.
-------------------------------
    Fix Version/s: 2.7.0
                   3.0.0-beta-2
                   2.6.2
                   2.5.12
     Hadoop Flags: Reviewed
       Resolution: Fixed

Pushed to all active branches.

Thanks [~junegunn] for contributing!

> Data loss in table cloned from a snapshot
> -----------------------------------------
>
>                 Key: HBASE-29111
>                 URL: https://issues.apache.org/jira/browse/HBASE-29111
>             Project: HBase
>          Issue Type: Bug
>          Components: dataloss, snapshots
>            Reporter: Junegunn Choi
>            Assignee: Junegunn Choi
>            Priority: Major
>              Labels: pull-request-available
>             Fix For: 2.7.0, 3.0.0-beta-2, 2.6.2, 2.5.12
>
>
> We experienced permanent data loss in a table cloned from a snapshot.
> Here's what we found.
>  * If you clone a table from a snapshot that contains split regions and 
> reference files, and immediately delete the snapshot, HBase can prematurely 
> delete the original HFiles causing data loss.
> h2. How to reproduce
> To quickly reproduce the issue, adjust the cleaner and janitor intervals and 
> set HFile TTL to zero. Also disable compaction so that reference files are 
> not compacted away. Or, you can put a lot of data so that compaction doesn't 
> finish during the test.
> {code:java}
>   <property>
>     <name>hbase.master.cleaner.interval</name>
>     <value>1000</value>
>   </property>
>   <property>
>     <name>hbase.catalogjanitor.interval</name>
>     <value>1000</value>
>   </property>
>   <property>
>     <name>hbase.master.hfilecleaner.ttl</name>
>     <value>0</value>
>   </property>
>   <property>
>     <name>hbase.regionserver.compaction.enabled</name>
>     <value>false</value>
>   </property>
> {code}
> And run this code on HBase shell.
> {code:java}
> # Create test table and write some data
> create 't', 'd'
> 10.times do |i|
>   put 't', i, 'd:foo', '_' * 1024
> end
> # Split in the middle and take the snapshot
> split 't', '5'
> snapshot 't', 's'
> # Drop the table and clone it from the snapshot
> disable 't'
> drop 't'
> clone_snapshot 's', 't'
> # Immediately delete the snapshot
> delete_snapshot 's'
> # Try disabling and re-enabling the table
> sleep 2
> disable 't'
> enable 't'
> # java.io.FileNotFoundException: HFileLink locations=[...]
> {code}
> h2. What actually happens
> User clones a table from a snapshot containing split regions and reference 
> files.
> {noformat}
> snapshot.RestoreSnapshotHelper: clone region=a23be88470c13611f6f24f20e0cf00ed 
> as a23be88470c13611f6f24f20e0cf00ed in snapshot s
> ...
> regionserver.HRegion: creating {ENCODED => a23be88470c13611f6f24f20e0cf00ed, 
> NAME => 't,40000000,1738562472443.a23be88470c13611f6f24f20e0cf00ed.', 
> STARTKEY => '40000000', ENDKEY => '80000000', OFFLINE => true, SPLIT => 
> true}, tableDescriptor='t', {TABLE_ATTRIBUTES => {METADATA => 
> {'hbase.store.file-tracker.impl' => 'DEFAULT'}}}, {NAME => 'd', 
> INDEX_BLOCK_ENCODING => 'NONE', VERSIONS => '1', KEEP_DELETED_CELLS => 
> 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => 
> '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', IN_MEMORY => 'false', 
> COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536 B (64KB)'}, 
> regionDir=file:/Users/jg/github/hbase/tmp/hbase
> ...
> snapshot.RestoreSnapshotHelper: finishing restore table regions using 
> snapshot=name: "s"
> {noformat}
> And the user deletes the snapshot.
> {noformat}
> snapshot.SnapshotManager: Deleting snapshot: s
> {noformat}
> After a while, CatalogJanitor garbage-collects the split parents as it sees 
> no daughter information in the meta table.
> {noformat}
> janitor.CatalogJanitor: Cleaning parent region {ENCODED => 
> a23be88470c13611f6f24f20e0cf00ed, NAME => 
> 't,40000000,1738562472443.a23be88470c13611f6f24f20e0cf00ed.', STARTKEY => 
> '40000000', ENDKEY => '80000000', OFFLINE => true, SPLIT => true}
> janitor.CatalogJanitor: Deleting region a23be88470c13611f6f24f20e0cf00ed 
> because daughters -- null, null -- no longer hold references
> {noformat}
> (see "{{{}null, null"{}}} part)
> This causes the HFileLinks to be archived.
> {noformat}
> backup.HFileArchiver: Archived from FileablePath, 
> file:/Users/jg/github/hbase/tmp/hbase/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/t=a23be88470c13611f6f24f20e0cf00ed-ecdd6aa22a6146599467839c56767522
>  to 
> file:/Users/jg/github/hbase/tmp/hbase/archive/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/t=a23be88470c13611f6f24f20e0cf00ed-ecdd6aa22a6146599467839c56767522
> {noformat}
> And the cleaners unanimously agree to delete the original HFile.
>  * We already deleted the snapshot, so SnapshotHFileCleaner won't complain.
>  * Because HFileLink is archived, HFileLinkCleaner won't complain.
> And the HFile is deleted before the daughter regions succeed to rebuild the 
> data in it through compaction.
> {noformat}
> cleaner.HFileCleaner: Removing 
> file:/Users/jg/github/hbase/tmp/hbase/archive/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/ecdd6aa22a6146599467839c56767522
> {noformat}
> And the data loss.
> {noformat}
> regionserver.CompactSplit: Compaction selection failed 
> region=t,6,1738562566034.8ad3785a3afe89e59b72db5d5d3a1bf5., 
> storeName=8ad3785a3afe89e59b72db5d5d3a1bf5/d, priority=14, 
> startTime=1738562622689
> java.io.FileNotFoundException: HFileLink locations=[
>   
> file:/Users/jg/github/hbase/tmp/hbase/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/ecdd6aa22a6146599467839c56767522,
>   
> file:/Users/jg/github/hbase/tmp/hbase/archive/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/ecdd6aa22a6146599467839c56767522,
>   
> file:/Users/jg/github/hbase/tmp/hbase/.tmp/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/ecdd6aa22a6146599467839c56767522,
>   
> file:/Users/jg/github/hbase/tmp/hbase/mobdir/data/default/t/a23be88470c13611f6f24f20e0cf00ed/d/ecdd6aa22a6146599467839c56767522
> ]
> {noformat}
> h2. Fix
> Make sure to put the split information to the meta table when cloning a 
> table. The information was already there, we just didn't use it.
> Let me open pull requests both on master and branch-2.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to