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

Aleksey Yeschenko commented on CASSANDRA-15204:
-----------------------------------------------

The following simple test is sufficient to demonstrate corruption without this 
validation in place:

{code}
    @Test
    public void dropRecreateIncompatibleColumnTest() throws Throwable
    {
        try (Cluster cluster = init(Cluster.create(1)))
        {
            cluster.schemaChange(format("CREATE TABLE %s.tbl (pk int PRIMARY 
KEY, foo int, bar set<text>);", KEYSPACE));

            cluster.coordinator(1).execute(format("INSERT INTO %s.tbl (pk, foo, 
bar) VALUES (1, 1, {'a'});", KEYSPACE), ONE);
            cluster.coordinator(1).execute(format("INSERT INTO %s.tbl (pk, foo, 
bar) VALUES (2, 2, {'b'});", KEYSPACE), ONE);
            cluster.get(1).runOnInstance(() -> 
FBUtilities.waitOnFutures(Keyspace.open(KEYSPACE).flush()));

            // drop and recreate 'bar', now as a simple 'text' column and not a 
set
            cluster.schemaChange(format("ALTER TABLE %s.tbl DROP bar;", 
KEYSPACE));
            cluster.schemaChange(format("ALTER TABLE %s.tbl ADD  bar text;", 
KEYSPACE));

            cluster.coordinator(1).execute(format("INSERT INTO %s.tbl (pk, foo, 
bar) VALUES (3, 3, 'c');", KEYSPACE), ONE);
            cluster.coordinator(1).execute(format("INSERT INTO %s.tbl (pk, foo, 
bar) VALUES (4, 4, 'd');", KEYSPACE), ONE);
            cluster.get(1).runOnInstance(() -> 
FBUtilities.waitOnFutures(Keyspace.open(KEYSPACE).flush()));

            // compact the two sstables together
            cluster.get(1).runOnInstance(() -> 
ColumnFamilyStore.getIfExists(KEYSPACE, "tbl").forceMajorCompaction());

            // restart
            cluster.get(1).shutdown(true).get();
            cluster.get(1).startup();

            assertRows(cluster.coordinator(1).execute(format("SELECT pk, foo, 
bar FROM %s.tbl", KEYSPACE), ONE),
                       new Object[][] {{ 1, 1, null }, { 2, 2, null },
                                       { 4, 4, "d"  }, { 3, 3, "c"  }});
        }
    }
{code}

Resulting in:

{code}
WARN  [SharedPool-Worker-1] node1 2019-07-09 17:25:11,907 
AbstractLocalAwareExecutorService.java:169 - Uncaught exception on thread 
Thread[SharedPool-Worker-1,5,node1]
java.lang.RuntimeException: 
org.apache.cassandra.io.sstable.CorruptSSTableException: Corrupted: 
/private/var/folders/jr/z8lrbjsn3kz27v4wt8ntnfqh0000gn/T/dtests5570532941954556030/node1/data/distributed_test_keyspace/tbl-1d880c50a26611e9b4f2a7fdb3b01932/md-3-big-Data.db
        at 
org.apache.cassandra.service.StorageProxy$DroppableRunnable.run(StorageProxy.java:2470)
 ~[main/:na]
        at 
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
~[na:1.8.0_212]
        at 
org.apache.cassandra.concurrent.AbstractLocalAwareExecutorService$FutureTask.run(AbstractLocalAwareExecutorService.java:164)
 ~[main/:na]
        at org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:109) 
[main/:na]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]
Caused by: org.apache.cassandra.io.sstable.CorruptSSTableException: Corrupted: 
/private/var/folders/jr/z8lrbjsn3kz27v4wt8ntnfqh0000gn/T/dtests5570532941954556030/node1/data/distributed_test_keyspace/tbl-1d880c50a26611e9b4f2a7fdb3b01932/md-3-big-Data.db
        at 
org.apache.cassandra.db.columniterator.AbstractSSTableIterator$Reader.hasNext(AbstractSSTableIterator.java:349)
 ~[main/:na]
        at 
org.apache.cassandra.db.filter.ClusteringIndexNamesFilter$1.hasNext(ClusteringIndexNamesFilter.java:157)
 ~[main/:na]
        at 
org.apache.cassandra.db.rows.LazilyInitializedUnfilteredRowIterator.computeNext(LazilyInitializedUnfilteredRowIterator.java:95)
 ~[main/:na]
        at 
org.apache.cassandra.db.rows.LazilyInitializedUnfilteredRowIterator.computeNext(LazilyInitializedUnfilteredRowIterator.java:32)
 ~[main/:na]
        at 
org.apache.cassandra.utils.AbstractIterator.hasNext(AbstractIterator.java:47) 
~[main/:na]
        at 
org.apache.cassandra.db.transform.BaseRows.hasNext(BaseRows.java:129) 
~[main/:na]
        at 
org.apache.cassandra.db.rows.LazilyInitializedUnfilteredRowIterator.computeNext(LazilyInitializedUnfilteredRowIterator.java:95)
 ~[main/:na]
        at 
org.apache.cassandra.db.rows.LazilyInitializedUnfilteredRowIterator.computeNext(LazilyInitializedUnfilteredRowIterator.java:32)
 ~[main/:na]
        at 
org.apache.cassandra.utils.AbstractIterator.hasNext(AbstractIterator.java:47) 
~[main/:na]
        at 
org.apache.cassandra.db.transform.BaseRows.hasNext(BaseRows.java:129) 
~[main/:na]
        at 
org.apache.cassandra.db.transform.UnfilteredRows.isEmpty(UnfilteredRows.java:71)
 ~[main/:na]
        at 
org.apache.cassandra.db.partitions.PurgeFunction.applyToPartition(PurgeFunction.java:75)
 ~[main/:na]
        at 
org.apache.cassandra.db.partitions.PurgeFunction.applyToPartition(PurgeFunction.java:26)
 ~[main/:na]
        at 
org.apache.cassandra.db.transform.BasePartitions.hasNext(BasePartitions.java:96)
 ~[main/:na]
        at 
org.apache.cassandra.db.partitions.UnfilteredPartitionIterators$Serializer.serialize(UnfilteredPartitionIterators.java:289)
 ~[main/:na]
        at 
org.apache.cassandra.db.ReadResponse$LocalDataResponse.build(ReadResponse.java:187)
 ~[main/:na]
        at 
org.apache.cassandra.db.ReadResponse$LocalDataResponse.<init>(ReadResponse.java:180)
 ~[main/:na]
        at 
org.apache.cassandra.db.ReadResponse$LocalDataResponse.<init>(ReadResponse.java:176)
 ~[main/:na]
        at 
org.apache.cassandra.db.ReadResponse.createDataResponse(ReadResponse.java:76) 
~[main/:na]
        at 
org.apache.cassandra.db.ReadCommand.createResponse(ReadCommand.java:341) 
~[main/:na]
        at 
org.apache.cassandra.service.StorageProxy$LocalReadRunnable.runMayThrow(StorageProxy.java:1785)
 ~[main/:na]
        at 
org.apache.cassandra.service.StorageProxy$DroppableRunnable.run(StorageProxy.java:2466)
 ~[main/:na]
        ... 4 common frames omitted
Caused by: java.io.IOException: Invalid Columns subset bytes; too many bits 
set:1
        at 
org.apache.cassandra.db.Columns$Serializer.deserializeSubset(Columns.java:530) 
~[main/:na]
        at 
org.apache.cassandra.db.rows.UnfilteredSerializer.deserializeRowBody(UnfilteredSerializer.java:484)
 ~[main/:na]
        at 
org.apache.cassandra.db.UnfilteredDeserializer$CurrentDeserializer.readNext(UnfilteredDeserializer.java:209)
 ~[main/:na]
        at 
org.apache.cassandra.db.columniterator.SSTableIterator$ForwardReader.computeNext(SSTableIterator.java:143)
 ~[main/:na]
        at 
org.apache.cassandra.db.columniterator.SSTableIterator$ForwardReader.hasNextInternal(SSTableIterator.java:172)
 ~[main/:na]
        at 
org.apache.cassandra.db.columniterator.AbstractSSTableIterator$Reader.hasNext(AbstractSSTableIterator.java:336)
 ~[main/:na]
        ... 25 common frames omitted
{code}

> Toughen up column drop/recreate validations in 3.0/3.11
> -------------------------------------------------------
>
>                 Key: CASSANDRA-15204
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-15204
>             Project: Cassandra
>          Issue Type: Bug
>          Components: Cluster/Schema
>            Reporter: Aleksey Yeschenko
>            Assignee: Aleksey Yeschenko
>            Priority: Normal
>             Fix For: 3.0.x, 3.11.x
>
>
> After CASSANDRA-8099 it’s no longer possible to safely drop/add columns with 
> incompatible types. In 4.0 we validate this correctly, but in 3.0 we don’t,
> and that can result in unreadable sstables (corrupted serialization headers 
> causing simple columns to be read as complex or vice versa).
> This patch brings 3.0 in line with 4.0 restrictions, making such corruption 
> impossible.



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

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

Reply via email to