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

Quanlong Huang updated IMPALA-15242:
------------------------------------
    Description: 
CatalogServiceCatalog.getOrLoadTable() will reload partitions of a 
transactional table when there are stale partitions. However, the check and 
update operations are not protected by table write lock. A concurrrent 
modification, e.g. EventProcessor processing COMMIT_COMPACTION_EVENT, could 
modify the partitions map and cause the reload in getOrLoadTable() fails.

Here is how the stale partitions are checked. It's protected by the table read 
lock. It then release the lock.
{code:java}
    List<HdfsPartition.Builder> partsToBeRefreshed = Collections.emptyList();
        ...
        readLock(tbl, catalogTimeline);
        try {
          partsToBeRefreshed =
              AcidUtils.getPartitionsForRefreshingFileMetadata(this, 
(HdfsTable) tbl);
        } finally {
          tbl.readLock().unlock();
        }{code}
[https://github.com/apache/impala/blob/01062ee897703c0b6c54cfedbe104acf363ff410/fe/src/main/java/org/apache/impala/catalog/CatalogServiceCatalog.java#L2864-L2865]

The table write lock will be acquired in refreshFileMetadata() when refreshing 
the partitions:
{code:java}
    if (!partsToBeRefreshed.isEmpty()) {
      return refreshFileMetadata((HdfsTable) tbl, partsToBeRefreshed, 
catalogTimeline);
    }{code}
[https://github.com/apache/impala/blob/01062ee897703c0b6c54cfedbe104acf363ff410/fe/src/main/java/org/apache/impala/catalog/CatalogServiceCatalog.java#L2891]

refreshFileMetadata() could fail if it uses stale partition ids. 
getOrLoadTable() then fails, which consequently fails the coordinator request.
{noformat}
E20260804 19:20:44.249446 134413 JniUtil.java:198] Error in Getting partial 
catalog object of TABLE:catalogd_meta_provider_test.insert_only. Time spent: 
2s019ms
I20260804 19:20:44.250008 134413 jni-util.cc:335] 
java.lang.IllegalStateException: Updating a non existing partition instance 
id=25
        at 
com.google.common.base.Preconditions.checkState(Preconditions.java:586)
        at 
org.apache.impala.catalog.HdfsTable.updatePartition(HdfsTable.java:1060)
        at 
org.apache.impala.catalog.HdfsTable.updatePartitions(HdfsTable.java:1051)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.refreshFileMetadata(CatalogServiceCatalog.java:4549)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.getOrLoadTable(CatalogServiceCatalog.java:2893)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.doGetPartialCatalogObject(CatalogServiceCatalog.java:4379)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.getPartialCatalogObject(CatalogServiceCatalog.java:4301)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.getPartialCatalogObject(CatalogServiceCatalog.java:4268)
        at 
org.apache.impala.service.JniCatalog.lambda$getPartialCatalogObject$10(JniCatalog.java:474)
        at 
org.apache.impala.service.JniCatalogOp.lambda$execAndSerialize$1(JniCatalogOp.java:90)
        at org.apache.impala.service.JniCatalogOp.execOp(JniCatalogOp.java:58)
        at 
org.apache.impala.service.JniCatalogOp.execAndSerialize(JniCatalogOp.java:89)
        at 
org.apache.impala.service.JniCatalogOp.execAndSerializeSilentStartAndFinish(JniCatalogOp.java:109)
        at 
org.apache.impala.service.JniCatalog.execAndSerializeSilentStartAndFinish(JniCatalog.java:256)
        at 
org.apache.impala.service.JniCatalog.getPartialCatalogObject(JniCatalog.java:473){noformat}
The issue can be reproduced by running 
CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction after 
applying the debug patch [^getOrLoadTable-bug-repro.patch] (on commit 
01062ee897).
{noformat}
(pushd fe && mvn test 
-Dtest=CatalogdMetaProviderTest#testTableFileMetadataAfterMinorCompaction)
...
[ERROR] 
org.apache.impala.catalog.local.CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction
  Time elapsed: 41.822 s  <<< ERROR!
org.apache.thrift.TException: IllegalStateException: Updating a non existing 
partition instance
        at 
org.apache.impala.catalog.local.CatalogdMetaProvider.sendRequest(CatalogdMetaProvider.java:503)
        at 
org.apache.impala.catalog.local.CatalogdMetaProvider.loadPartitionsFromCatalogd(CatalogdMetaProvider.java:1145)
        at 
org.apache.impala.catalog.local.CatalogdMetaProvider.loadPartitionsByRefs(CatalogdMetaProvider.java:1063)
        at 
org.apache.impala.catalog.local.CatalogdMetaProviderTest.loadPartitions(CatalogdMetaProviderTest.java:212)
        at 
org.apache.impala.catalog.local.CatalogdMetaProviderTest.loadPartitions(CatalogdMetaProviderTest.java:229)
        at 
org.apache.impala.catalog.local.CatalogdMetaProviderTest.testFileMetadataAfterCompaction(CatalogdMetaProviderTest.java:685)
        at 
org.apache.impala.catalog.local.CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction(CatalogdMetaProviderTest.java:607){noformat}

  was:
CatalogServiceCatalog.getOrLoadTable() will reload partitions of a 
transactional table when there are stale partitions. However, the check and 
update operations are not protected by table write lock. A concurrrent 
modification, e.g. EventProcessor processing COMMIT_COMPACTION_EVENT, could 
modify the partitions map and cause the reload in getOrLoadTable() fails.

Here is how the stale partitions are checked. It's protected by the table read 
lock. It then release the lock.
{code:java}
    List<HdfsPartition.Builder> partsToBeRefreshed = Collections.emptyList();
        ...
        readLock(tbl, catalogTimeline);
        try {
          partsToBeRefreshed =
              AcidUtils.getPartitionsForRefreshingFileMetadata(this, 
(HdfsTable) tbl);
        } finally {
          tbl.readLock().unlock();
        }{code}
[https://github.com/apache/impala/blob/01062ee897703c0b6c54cfedbe104acf363ff410/fe/src/main/java/org/apache/impala/catalog/CatalogServiceCatalog.java#L2864-L2865]

The table write lock will be acquired in refreshFileMetadata() when refreshing 
the partitions:
{code:java}
    if (!partsToBeRefreshed.isEmpty()) {
      return refreshFileMetadata((HdfsTable) tbl, partsToBeRefreshed, 
catalogTimeline);
    }{code}
[https://github.com/apache/impala/blob/01062ee897703c0b6c54cfedbe104acf363ff410/fe/src/main/java/org/apache/impala/catalog/CatalogServiceCatalog.java#L2891]

refreshFileMetadata() could fail if it uses stale partition ids. 
getOrLoadTable() then fails, which consequently fails the coordinator request.
{noformat}
E20260804 19:20:44.249446 134413 JniUtil.java:198] Error in Getting partial 
catalog object of TABLE:catalogd_meta_provider_test.insert_only. Time spent: 
2s019ms
I20260804 19:20:44.250008 134413 jni-util.cc:335] 
java.lang.IllegalStateException: Updating a non existing partition instance 
id=25
        at 
com.google.common.base.Preconditions.checkState(Preconditions.java:586)
        at 
org.apache.impala.catalog.HdfsTable.updatePartition(HdfsTable.java:1060)
        at 
org.apache.impala.catalog.HdfsTable.updatePartitions(HdfsTable.java:1051)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.refreshFileMetadata(CatalogServiceCatalog.java:4549)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.getOrLoadTable(CatalogServiceCatalog.java:2893)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.doGetPartialCatalogObject(CatalogServiceCatalog.java:4379)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.getPartialCatalogObject(CatalogServiceCatalog.java:4301)
        at 
org.apache.impala.catalog.CatalogServiceCatalog.getPartialCatalogObject(CatalogServiceCatalog.java:4268)
        at 
org.apache.impala.service.JniCatalog.lambda$getPartialCatalogObject$10(JniCatalog.java:474)
        at 
org.apache.impala.service.JniCatalogOp.lambda$execAndSerialize$1(JniCatalogOp.java:90)
        at org.apache.impala.service.JniCatalogOp.execOp(JniCatalogOp.java:58)
        at 
org.apache.impala.service.JniCatalogOp.execAndSerialize(JniCatalogOp.java:89)
        at 
org.apache.impala.service.JniCatalogOp.execAndSerializeSilentStartAndFinish(JniCatalogOp.java:109)
        at 
org.apache.impala.service.JniCatalog.execAndSerializeSilentStartAndFinish(JniCatalog.java:256)
        at 
org.apache.impala.service.JniCatalog.getPartialCatalogObject(JniCatalog.java:473){noformat}
The issue can be reproduced by running 
CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction after 
applying the debug patch [^getOrLoadTable-bug-repro.patch] (on commit 
01062ee897).
{code}
(pushd fe && mvn test 
-Dtest=CatalogdMetaProviderTest#testTableFileMetadataAfterMinorCompaction){code}


> getOrLoadTable should hold table write lock in reloading partitions
> -------------------------------------------------------------------
>
>                 Key: IMPALA-15242
>                 URL: https://issues.apache.org/jira/browse/IMPALA-15242
>             Project: IMPALA
>          Issue Type: Bug
>          Components: Catalog
>            Reporter: Quanlong Huang
>            Priority: Major
>         Attachments: getOrLoadTable-bug-repro.patch
>
>
> CatalogServiceCatalog.getOrLoadTable() will reload partitions of a 
> transactional table when there are stale partitions. However, the check and 
> update operations are not protected by table write lock. A concurrrent 
> modification, e.g. EventProcessor processing COMMIT_COMPACTION_EVENT, could 
> modify the partitions map and cause the reload in getOrLoadTable() fails.
> Here is how the stale partitions are checked. It's protected by the table 
> read lock. It then release the lock.
> {code:java}
>     List<HdfsPartition.Builder> partsToBeRefreshed = Collections.emptyList();
>         ...
>         readLock(tbl, catalogTimeline);
>         try {
>           partsToBeRefreshed =
>               AcidUtils.getPartitionsForRefreshingFileMetadata(this, 
> (HdfsTable) tbl);
>         } finally {
>           tbl.readLock().unlock();
>         }{code}
> [https://github.com/apache/impala/blob/01062ee897703c0b6c54cfedbe104acf363ff410/fe/src/main/java/org/apache/impala/catalog/CatalogServiceCatalog.java#L2864-L2865]
> The table write lock will be acquired in refreshFileMetadata() when 
> refreshing the partitions:
> {code:java}
>     if (!partsToBeRefreshed.isEmpty()) {
>       return refreshFileMetadata((HdfsTable) tbl, partsToBeRefreshed, 
> catalogTimeline);
>     }{code}
> [https://github.com/apache/impala/blob/01062ee897703c0b6c54cfedbe104acf363ff410/fe/src/main/java/org/apache/impala/catalog/CatalogServiceCatalog.java#L2891]
> refreshFileMetadata() could fail if it uses stale partition ids. 
> getOrLoadTable() then fails, which consequently fails the coordinator request.
> {noformat}
> E20260804 19:20:44.249446 134413 JniUtil.java:198] Error in Getting partial 
> catalog object of TABLE:catalogd_meta_provider_test.insert_only. Time spent: 
> 2s019ms
> I20260804 19:20:44.250008 134413 jni-util.cc:335] 
> java.lang.IllegalStateException: Updating a non existing partition instance 
> id=25
>         at 
> com.google.common.base.Preconditions.checkState(Preconditions.java:586)
>         at 
> org.apache.impala.catalog.HdfsTable.updatePartition(HdfsTable.java:1060)
>         at 
> org.apache.impala.catalog.HdfsTable.updatePartitions(HdfsTable.java:1051)
>         at 
> org.apache.impala.catalog.CatalogServiceCatalog.refreshFileMetadata(CatalogServiceCatalog.java:4549)
>         at 
> org.apache.impala.catalog.CatalogServiceCatalog.getOrLoadTable(CatalogServiceCatalog.java:2893)
>         at 
> org.apache.impala.catalog.CatalogServiceCatalog.doGetPartialCatalogObject(CatalogServiceCatalog.java:4379)
>         at 
> org.apache.impala.catalog.CatalogServiceCatalog.getPartialCatalogObject(CatalogServiceCatalog.java:4301)
>         at 
> org.apache.impala.catalog.CatalogServiceCatalog.getPartialCatalogObject(CatalogServiceCatalog.java:4268)
>         at 
> org.apache.impala.service.JniCatalog.lambda$getPartialCatalogObject$10(JniCatalog.java:474)
>         at 
> org.apache.impala.service.JniCatalogOp.lambda$execAndSerialize$1(JniCatalogOp.java:90)
>         at org.apache.impala.service.JniCatalogOp.execOp(JniCatalogOp.java:58)
>         at 
> org.apache.impala.service.JniCatalogOp.execAndSerialize(JniCatalogOp.java:89)
>         at 
> org.apache.impala.service.JniCatalogOp.execAndSerializeSilentStartAndFinish(JniCatalogOp.java:109)
>         at 
> org.apache.impala.service.JniCatalog.execAndSerializeSilentStartAndFinish(JniCatalog.java:256)
>         at 
> org.apache.impala.service.JniCatalog.getPartialCatalogObject(JniCatalog.java:473){noformat}
> The issue can be reproduced by running 
> CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction after 
> applying the debug patch [^getOrLoadTable-bug-repro.patch] (on commit 
> 01062ee897).
> {noformat}
> (pushd fe && mvn test 
> -Dtest=CatalogdMetaProviderTest#testTableFileMetadataAfterMinorCompaction)
> ...
> [ERROR] 
> org.apache.impala.catalog.local.CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction
>   Time elapsed: 41.822 s  <<< ERROR!
> org.apache.thrift.TException: IllegalStateException: Updating a non existing 
> partition instance
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProvider.sendRequest(CatalogdMetaProvider.java:503)
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProvider.loadPartitionsFromCatalogd(CatalogdMetaProvider.java:1145)
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProvider.loadPartitionsByRefs(CatalogdMetaProvider.java:1063)
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProviderTest.loadPartitions(CatalogdMetaProviderTest.java:212)
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProviderTest.loadPartitions(CatalogdMetaProviderTest.java:229)
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProviderTest.testFileMetadataAfterCompaction(CatalogdMetaProviderTest.java:685)
>       at 
> org.apache.impala.catalog.local.CatalogdMetaProviderTest.testTableFileMetadataAfterMinorCompaction(CatalogdMetaProviderTest.java:607){noformat}



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

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to