You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by "maxwellguo (Jira)" <ji...@apache.org> on 2020/06/02 03:44:00 UTC
[jira] [Updated] (CASSANDRA-15844) Create table Asynchronously or
creating table contact the same node from many client threads at same time
may causing data lose
[ https://issues.apache.org/jira/browse/CASSANDRA-15844?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
maxwellguo updated CASSANDRA-15844:
-----------------------------------
Summary: Create table Asynchronously or creating table contact the same node from many client threads at same time may causing data lose (was: Create table Asynchronously or contact the same node from many client threads at same time may causing data lose)
> Create table Asynchronously or creating table contact the same node from many client threads at same time may causing data lose
> -------------------------------------------------------------------------------------------------------------------------------
>
> Key: CASSANDRA-15844
> URL: https://issues.apache.org/jira/browse/CASSANDRA-15844
> Project: Cassandra
> Issue Type: Bug
> Components: Cluster/Schema
> Reporter: maxwellguo
> Assignee: maxwellguo
> Priority: Normal
> Attachments: createkeyspace.jpg, keyspace inner.jpg, schemaversion.jpg
>
>
> When creating a table from on one coordinator node from some client threads at the same time, Or creating a table using session.executeAsync() method, may cause the schema'information incorrect. Seriously will causing data lose.
> For my test. I use executeAsync() to create table one by one using the same table name (Though I do konw create table should be synchronously, but some of our customers may create table using executAsync() ). My expectations is that the last cql
> {code:java}
> CREATE TABLE ks.tb (name text PRIMARY KEY , age int, adds text, height text)
> {code}
> should take effect .
> !createkeyspace.jpg!
> But after runing the code, I foud that the result is not what I am expected. the schema struct is is :
> {code:java}
> CREATE TABLE ks.tb (name text PRIMARY KEY , age int, adds text, sex int, height int)
> {code}
> !keyspace inner.jpg!
> And the schema version in the memory and on the disk is not the same.
> !schemaversion.jpg!
> When add a new columnfamily (creat a new table), the request of creating same table with different schema definition arrived at the same time from different clients or using
> executeAsync method.
> {code:java}
> private static void announceNewColumnFamily(CFMetaData cfm, boolean announceLocally, boolean throwOnDuplicate, long timestamp) throws ConfigurationException
> {
> cfm.validate();
> KeyspaceMetadata ksm = Schema.instance.getKSMetaData(cfm.ksName);
> if (ksm == null)
> throw new ConfigurationException(String.format("Cannot add table '%s' to non existing keyspace '%s'.", cfm.cfName, cfm.ksName));
> // If we have a table or a view which has the same name, we can't add a new one
> else if (throwOnDuplicate && ksm.getTableOrViewNullable(cfm.cfName) != null)
> throw new AlreadyExistsException(cfm.ksName, cfm.cfName);
> logger.info("Create new table: {}", cfm);
> announce(SchemaKeyspace.makeCreateTableMutation(ksm, cfm, timestamp), announceLocally);
> }
> {code}
> The code of checking table existance may failed. And same table's request may all going to do announce() method;
> {code:java}
> public static synchronized void mergeSchema(Collection<Mutation> mutations, boolean forDynamoTTL)
> {
> // only compare the keyspaces affected by this set of schema mutations
> Set<String> affectedKeyspaces =
> mutations.stream()
> .map(m -> UTF8Type.instance.compose(m.key().getKey()))
> .collect(Collectors.toSet());
> // fetch the current state of schema for the affected keyspaces only
> Keyspaces before = Schema.instance.getKeyspaces(affectedKeyspaces);
> // apply the schema mutations and flush
> mutations.forEach(Mutation::apply);
> if (FLUSH_SCHEMA_TABLES)
> flush();
> // fetch the new state of schema from schema tables (not applied to Schema.instance yet)
> Keyspaces after = fetchKeyspacesOnly(affectedKeyspaces);
> mergeSchema(before, after);
> scheduleDynamoTTLClean(forDynamoTTL, mutations);
> }
> {code}
> For we may write the new table definition into disk, so at last we saw
> {code:java}
> CREATE TABLE ks.tb (name text PRIMARY KEY , age int, adds text, sex int, height int)
> {code}
> in our case.
> And we also saw the different version in memory and disk.
> when writing data we using the schema in memory, but when we doing node restart the schema definition on disk will be used. Then may causing data lose.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org