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

Brandon Williams updated CASSANDRA-21733:
-----------------------------------------
     Bug Category: Parent values: Correctness(12982)Level 1 values: Recoverable 
Corruption / Loss(12986)
       Complexity: Normal
    Discovered By: User Report
    Fix Version/s: 4.0.x
                   4.1.x
                   5.0.x
                   6.x
                   7.x
         Severity: Normal
           Status: Open  (was: Triage Needed)

> Reads fail after ALTER TABLE DROP ... USING TIMESTAMP older than the column's 
> data
> ----------------------------------------------------------------------------------
>
>                 Key: CASSANDRA-21733
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21733
>             Project: Apache Cassandra
>          Issue Type: Bug
>          Components: CQL/Interpreter, Legacy/Local Write-Read Paths
>            Reporter: Nadav Har'El
>            Priority: Normal
>             Fix For: 4.0.x, 4.1.x, 5.0.x, 6.x, 7.x
>
>
> *Affects versions:*{color:#616161} 4.1.12, 5.0.9, 6.0-alpha2 (tested on the 
> official Docker images); probably all versions since 4.0 or earlier{color}
> When a regular column is dropped with {{{}ALTER TABLE ... DROP col USING 
> TIMESTAMP t{}}}, and the column still holds cells with timestamps newer than 
> {{{}t{}}}, reads of that table fail. The coordinator returns a ReadFailure to 
> the client, and the replica logs an IllegalStateException while serializing 
> the read response.
> Reproducer (single node, cqlsh):
> {code:sql}
> CREATE KEYSPACE ks WITH replication = {'class': 'SimpleStrategy', 
> 'replication_factor': 1};
> CREATE TABLE ks.t (a int PRIMARY KEY, c int, f int);
> INSERT INTO ks.t (a, c, f) VALUES (1, 2, 3);
> ALTER TABLE ks.t DROP f USING TIMESTAMP 20000;
> SELECT * FROM ks.t;
> {code}
> The {{SELECT}} fails:
> {noformat}
> ReadFailure: Error from server: code=1300 [Replica(s) failed to execute read] 
> message="Operation failed - received 0 responses and 1 failures: UNKNOWN from 
> /127.0.0.1:7000"
> {noformat}
> and the node logs:
> {noformat}
> java.lang.RuntimeException: java.lang.IllegalStateException: [c, f] is not a 
> subset of [c]
> at 
> org.apache.cassandra.service.StorageProxy$DroppableRunnable.run(StorageProxy.java:3159)
> ...
> Caused by: java.lang.IllegalStateException: [c, f] is not a subset of [c]
> at org.apache.cassandra.db.Columns$Serializer.encodeBitmap(Columns.java:618)
> at 
> org.apache.cassandra.db.Columns$Serializer.serializeSubset(Columns.java:548)
> at 
> org.apache.cassandra.db.rows.UnfilteredSerializer.serializeRowBody(UnfilteredSerializer.java:242)
> ...
> at 
> org.apache.cassandra.db.ReadResponse$LocalDataResponse.build(ReadResponse.java:262)
> at org.apache.cassandra.db.ReadCommand.createResponse(ReadCommand.java:453)
> at 
> org.apache.cassandra.service.StorageProxy$LocalReadRunnable.runMayThrow(StorageProxy.java:2756)
> {noformat}
> (Stack trace from 6.0-alpha2; 4.1 and 5.0 fail the same way.)
> Observations:
>  * The same sequence without {{USING TIMESTAMP}} (so the drop time is newer 
> than the data) works correctly.
>  * The INSERT doesn't need an explicit timestamp. Any data newer than the 
> drop timestamp triggers the bug. In practice that can happen with clock skew, 
> client-provided timestamps, or a schema restored with explicit {{DROP ... 
> USING TIMESTAMP}} statements, like the ones DESCRIBE and snapshots' 
> schema.cql emit for dropped columns.
>  * The table doesn't need another regular column. With {{{}CREATE TABLE ks.t 
> (a int PRIMARY KEY, f int){}}}, the error becomes {{{}[f] is not a subset of 
> []{}}}.
>  * Range scans ({{{}SELECT * FROM ks.t{}}}) fail for every table we tried. 
> Single-partition reads ({{{}WHERE a = 1{}}}) also fail when the table has a 
> clustering key, e.g. {{{}PRIMARY KEY (a, b){}}}, but succeed in the example 
> above without one.
>  * The error is in serializing the read response. The row still contains the 
> dropped column {{{}f{}}}, apparently because its cells are newer than the 
> drop time, but the serialization header's column set doesn't include it.
> *Why the existing unit tests don't catch this:*
> The unit tests that drop a column {{USING TIMESTAMP}} older than its data 
> don't detect this bug:
>  * {{{}AlterTest.testDropWithTimestamp{}}}, {{testDropStaticWithTimestamp}} 
> and {{testDropMultipleWithTimestamp}} re-ADD the dropped column before 
> reading the table, so they never read a table whose dropped column still has 
> newer data.
>  * {{CreateLikeTest.testCopyAfterAlterTable}} does exactly that: it runs 
> {{ALTER TABLE ... DROP f USING TIMESTAMP 20000}} after writing {{f}} with 
> current timestamps, and then reads the table. It passes because CQLTester's 
> {{execute()}} runs queries through {{{}QueryProcessor.executeInternal(){}}}, 
> which reads locally without building a serialized {{{}ReadResponse{}}}, and 
> that serialization is where the bug is. The same test fails when its 
> statements are sent through the native protocol (e.g. with 
> {{{}executeNet(){}}}). We found this while translating CreateLikeTest to 
> ScyllaDB's Python-based CQL tests, which run against a real Cassandra node 
> through the Python driver.
> Related: CASSANDRA-21607 reports a similar scenario, a dropped non-frozen 
> collection that still holds cells newer than the drop time, which causes a 
> NullPointerException in reads and compaction. This issue is the same 
> situation for a simple (non-collection) column. It fails differently, in 
> read-response serialization, but may have the same root cause.
>  



--
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