Database: Cassandra 2.1.2 (single node)
Database driver: Cassandra driver 2.1.6.
Application: DropWizard 0.7.1
I have a simple table in my database:
cqlsh:ugc> desc table person;
CREATE TABLE abc.person (
id uuid PRIMARY KEY
) WITH bloom_filter_fp_chance = 0.01
AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
AND comment = ''
AND compaction = {'min_threshold': '4', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32'}
AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
AND dclocal_read_repair_chance = 0.1
AND default_time_to_live = 0
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99.0PERCENTILE';
And the table contains some data:
cqlsh:ugc> select * from person;
id
--------------------------------------
bf56c8b1-ed0b-44d6-bd45-0d55dd73fbe0
In my DropWizard application, I have a mapped object:
@Table(name = "person")
public class Person {
@PartitionKey
@Column(name ="id")
UUID id;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
}
Everything works well. I am able to retrieve the data from my DropWizard application. However, when I
1) add a new column 'name' to the table
cqlsh:ugc> ALTER TABLE abc.person ADD name text;
cqlsh:ugc> desc table person;
CREATE TABLE abc.person (
id uuid PRIMARY KEY,
name text
) WITH bloom_filter_fp_chance = 0.01
AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
AND comment = ''
AND compaction = {'min_threshold': '4', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32'}
AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
AND dclocal_read_repair_chance = 0.1
AND default_time_to_live = 0
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99.0PERCENTILE';
cqlsh:ugc> select * from person;
id | name
--------------------------------------+------
bf56c8b1-ed0b-44d6-bd45-0d55dd73fbe0 | null
2) update the Person object to map the new column
@Table(name = "person")
public class Person {
@PartitionKey
@Column(name ="id")
UUID id;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
@Column(name = "name")
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3) restart DropWizard application
The application throws an exception:
java.lang.IllegalArgumentException: "name" is not a column defined in this metadata
Error looks like it's saying the model is trying to map the column 'name' that doesn't exist in the database table, when in fact it's there from the database point of view.
But, if I restart my database, it seems to fix the issue.
It looks like, alter table requires database restart when your table contains existing records. The issue does not occur when the table is empty and the new column is added (does not require restart). I couldn't find any documentation from [http://docs.datastax.com/en/cql/3.0/cql/cql_reference/alter_table_r.html] that deals with my situation.
Question:
Is there a way I can alter a table without restarting my database? If so, how do I do it? If not, can anybody explain why database restart is required?
On my side, I don't need restart DB to update the schema. I don't know how you restart your application. I suggest you stop your application and search if any process still running for the application and start your application.
It seems that some connection for DB not break while your restarting application, and you stop DB then force the connection stoped, then change work.