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

Viraj Jasani reassigned PHOENIX-8053:
-------------------------------------

    Assignee: Viraj Jasani

> Concurrency bugs related to conditional UPSERTs on same row
> -----------------------------------------------------------
>
>                 Key: PHOENIX-8053
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-8053
>             Project: Phoenix
>          Issue Type: Bug
>            Reporter: Viraj Jasani
>            Assignee: Viraj Jasani
>            Priority: Major
>
> Concurrent conditional UPSERT on the same row can fail, return uncommitted 
> data, or lose updates.
> While one update on the data table is writing to its indexes, the update 
> releases the row lock. A later concurrent update on the same row builds on 
> the earlier update's pending state in memory (not from disk). However, this 
> tracking of the pending updates can cause issues.
> Some of the issues as of today:
>  * *Non-retryable error after a no-op:* A conditional upsert (ON DUPLICATE 
> KEY) whose condition is false changes nothing and needs to return early, but 
> it stays recorded as the row's latest pending update. The next concurrent 
> UPSERT on the row finds it as completed and fails with a non-retryable 
> {*}IllegalArgumentException: the phase of the last batch cannot be POST{*}.
>  * *No-op result based on uncommitted data:* A conditional upsert whose 
> condition is false returns to the client right away. Its result, including 
> the returned row, can be based on the earlier update's pending state in 
> memory. If that update fails, the client was provided result based on 
> uncommitted data.
>  * *Lost update after a failed update:* The row's latest pending update fails 
> while an earlier update is still pending. The next update reads the row from 
> disk (latest update failed) and misses the earlier pending write (which has 
> not completed yet), and then overwrites it once both commit.
>  * *Pending tracking removed too early:* Some updates never register as 
> pending on the row: whole-row upserts on an immutable table with a global or 
> uncovered index, or on a mutable table whose only indexes are uncovered. When 
> such an update completes, it still removes the row's pending entry, even the 
> one that a later update created. The next update reads from disk and misses a 
> write that is still in progress.
> Also, the batches chained on a busy row (the pending ones and the ones 
> already done) stay in memory as long as the row has updates in flight.
> Sample Exception for first case:
>  
> {code:java}
> Caused by: org.apache.phoenix.execute.CommitException: 
> org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 1 
> action: org.apache.phoenix.hbase.index.builder.IndexBuildingFailureException: 
> Failed to build index for unexpected reason!       at 
> org.apache.phoenix.hbase.index.util.IndexManagementUtil.rethrowIndexingException(IndexManagementUtil.java:218)
>        at 
> org.apache.phoenix.hbase.index.IndexRegionObserver.preBatchMutate(IndexRegionObserver.java:706)
>       at 
> org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost$28.call(RegionCoprocessorHost.java:1002)
>   at 
> org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost$28.call(RegionCoprocessorHost.java:999)
>    at 
> org.apache.hadoop.hbase.coprocessor.CoprocessorHost$ObserverOperationWithoutResult.callObserver(CoprocessorHost.java:558)
>     at 
> org.apache.hadoop.hbase.coprocessor.CoprocessorHost.execOperation(CoprocessorHost.java:631)
>   at 
> org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost.preBatchMutate(RegionCoprocessorHost.java:999)
>     at 
> org.apache.hadoop.hbase.regionserver.HRegion$MutationBatchOperation.prepareMiniBatchOperations(HRegion.java:3859)
>     at 
> org.apache.hadoop.hbase.regionserver.HRegion.doMiniBatchMutate(HRegion.java:4577)
>     at 
> org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:4515)  
> at 
> org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:4437)  
> at 
> org.apache.hadoop.hbase.regionserver.RSRpcServices.doBatchOp(RSRpcServices.java:1036)
>         at 
> org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicBatchOp(RSRpcServices.java:954)
>         at 
> org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicRegionMutation(RSRpcServices.java:919)
>  at 
> org.apache.hadoop.hbase.regionserver.RSRpcServices.multi(RSRpcServices.java:2897)
>     at 
> org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:45039)
>    at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:416)       at 
> org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:124)      at 
> org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:102)      at 
> org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:82)Caused by: 
> java.lang.IllegalArgumentException: the phase of the last batch cannot be 
> POST      at 
> org.apache.phoenix.thirdparty.com.google.common.base.Preconditions.checkArgument(Preconditions.java:141)
>      at 
> org.apache.phoenix.hbase.index.IndexRegionObserver.getCurrentRowStates(IndexRegionObserver.java:1264)
>         at 
> org.apache.phoenix.hbase.index.IndexRegionObserver.preBatchMutateWithExceptions(IndexRegionObserver.java:2029)
>        at 
> org.apache.phoenix.hbase.index.IndexRegionObserver.preBatchMutate(IndexRegionObserver.java:703)
>       ... 18 more
> {code}
>  
>  



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to