You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@phoenix.apache.org by "James Taylor (JIRA)" <ji...@apache.org> on 2018/02/15 07:51:02 UTC

[jira] [Commented] (PHOENIX-4608) Concurrent modification of bitset in ProjectedColumnExpression

    [ https://issues.apache.org/jira/browse/PHOENIX-4608?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16365209#comment-16365209 ] 

James Taylor commented on PHOENIX-4608:
---------------------------------------

Nice job tracking this down, [~sergey.soldatov]. Couple of comments:
- Where is the ProjectedColumnExpression being used by multiple threads? The one place I know about is when an UPSERT SELECT statement is run client side, but in that case we clone any expressions that store state. I just want to make sure we don't have a systemic issue.
- On the server-side, each scan being processed should have it's own copy of ProjectedColumnExpression.
- If we have to use the same the same ProjectedColumnExpression, I'd be more inclined to just instantiate the ValueBitSet in the evaluate method. It's like a regular bit set so will only have (in most cases) a long array of a single element.

> Concurrent modification of bitset in ProjectedColumnExpression
> --------------------------------------------------------------
>
>                 Key: PHOENIX-4608
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-4608
>             Project: Phoenix
>          Issue Type: Bug
>    Affects Versions: 4.14.0
>            Reporter: Sergey Soldatov
>            Assignee: Sergey Soldatov
>            Priority: Major
>             Fix For: 4.14.0
>
>         Attachments: PHOENIX-4608-v1.patch
>
>
> in ProjectedColumnExpression we are using an instance of ValueBitSet to track nulls during evaluate calls. We are using a single instance of ProjectedColumnExpression per column across all threads running in parallel, so it may happen that one thread call bitSet.clear() and another thread is using it in isNull at the same time, making a wrong assumption that the value is null.  We saw that problem when query like 
> {noformat}
> upsert into C select trim (A.ID), B.B From (select ID, SUM(1) as B from T1 group by ID) as B join T2 as A on A.ID = B.ID;  
> {noformat}
> During the execution earlier mentioned condition happen and we don't advance from the char column (A.ID)  to long (B.B) and get an exception like
> {noformat}
> Error: ERROR 201 (22000): Illegal data. BIGINT value -6908486506036322272 cannot be cast to Integer without changing its value (state=22000,code=201) 
> java.sql.SQLException: ERROR 201 (22000): Illegal data. BIGINT value -6908486506036322272 cannot be cast to Integer without changing its value 
> at org.apache.phoenix.exception.SQLExceptionCode$Factory$1.newException(SQLExceptionCode.java:442) 
> at org.apache.phoenix.exception.SQLExceptionInfo.buildException(SQLExceptionInfo.java:150) 
> at org.apache.phoenix.util.ServerUtil.parseRemoteException(ServerUtil.java:129) 
> at org.apache.phoenix.util.ServerUtil.parseServerExceptionOrNull(ServerUtil.java:118) 
> at org.apache.phoenix.util.ServerUtil.parseServerException(ServerUtil.java:107) 
> at org.apache.phoenix.iterate.BaseResultIterators.getIterators(BaseResultIterators.java:771) 
> at org.apache.phoenix.iterate.BaseResultIterators.getIterators(BaseResultIterators.java:714) 
> at org.apache.phoenix.iterate.RoundRobinResultIterator.getIterators(RoundRobinResultIterator.java:176) 
> at org.apache.phoenix.iterate.RoundRobinResultIterator.next(RoundRobinResultIterator.java:91) 
> at org.apache.phoenix.iterate.DelegateResultIterator.next(DelegateResultIterator.java:44) 
> at org.apache.phoenix.compile.UpsertCompiler$2.execute(UpsertCompiler.java:797) 
> at org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:343) 
> at org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:331) 
> at org.apache.phoenix.call.CallRunner.run(CallRunner.java:53) 
> at org.apache.phoenix.jdbc.PhoenixStatement.executeMutation(PhoenixStatement.java:329) 
> at org.apache.phoenix.jdbc.PhoenixStatement.execute(PhoenixStatement.java:1440) 
> at sqlline.Commands.execute(Commands.java:822) 
> at sqlline.Commands.sql(Commands.java:732) 
> at sqlline.SqlLine.dispatch(SqlLine.java:808) 
> at sqlline.SqlLine.begin(SqlLine.java:681) 
> at sqlline.SqlLine.start(SqlLine.java:398) 
> at sqlline.SqlLine.main(SqlLine.java:292)
> {noformat}
> Fortunately, bitSet is the only field we continuously modify in that class, so we may fix this problem by making it ThreadLocal. 



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)