Skip to content

Commit c24d5f7

Browse files
tolbertamolim7t
authored andcommitted
JAVA-1276: FAQ Entry for tombstone messages (apache#735)
Adds an FAQ entry for how tombstones could possibly be created using the driver and how to avoid doing so.
1 parent d90f192 commit c24d5f7

1 file changed

Lines changed: 56 additions & 1 deletion

File tree

faq/README.md

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,59 @@ and we've had many reports where the problem turned out to be in user code.
157157

158158
See [Blobs.java] in the `driver-examples` module for some examples and explanations.
159159

160-
[Blobs.java]: https://github.com/datastax/java-driver/tree/3.0.x/driver-examples/src/main/java/com/datastax/driver/examples/datatypes/Blobs.java
160+
161+
### Why am I seeing messages about `tombstone_warn_threshold` or `tombstone_fail_threshold` being exceeded in my Cassandra logs?
162+
163+
Applications which use the object mapper or set `null` values in their
164+
statements may observe that many tombstones are being stored in their tables
165+
which subsequently may lead to poor query performance, failed queries, or
166+
columns being mysteriously deleted.
167+
168+
This is caused by INSERT/UPDATE statements containing `null` values for columns
169+
that a user does not intend to change. Common circumstances around this come
170+
from using the object mapper or writing your own persistence layer and
171+
attempting to reuse the same `PreparedStatement` for inserting data, even with
172+
partial updates.
173+
174+
Prior to cassandra 2.2, there was no means of reusing the same
175+
`PreparedStatement` for making partial updates to different columns.
176+
177+
For example, given the following code:
178+
179+
```java
180+
PreparedStatement prepared = session.prepare("INSERT INTO contacts (email, firstname, lastname) VALUES (?, ?, ?)");
181+
BoundStatement bound = prepared.bind();
182+
bound.set("email", "clint.barton@hawkeye.com");
183+
bound.set("firstname", "Barney");
184+
// creates a tombstone!!
185+
bound.set("lastname", null);
186+
```
187+
188+
If one wanted to use this query to update only `firstname` this would not
189+
be achievable without binding the `lastname` parameter to `null`. This would
190+
have an undesired side effect of creating a tombstone for `lastname` and thus
191+
to the user giving the impression that `lastname` was deleted.
192+
193+
In cassandra 2.2 and later with protocol v4, bind parameters (`?`) can
194+
optionally be left unset
195+
([CASSANDRA-7304]):
196+
197+
```java
198+
PreparedStatement prepared = session.prepare("INSERT INTO contacts (email, firstname, lastname) VALUES (?, ?, ?)");
199+
BoundStatement bound = prepared.bind();
200+
bound.set("email", "clint.barton@hawkeye.com");
201+
bound.set("firstname", "Barney");
202+
// lastname is left unset.
203+
```
204+
205+
See [Parameters and Binding] for more details about unset parameters.
206+
207+
Another possible root cause for this is using the object mapper and leaving
208+
fields set to `null`. This also causes tombstones to be inserted unless
209+
setting `saveNullFields` option to false. See [Mapper options] for more
210+
details.
211+
212+
[Blobs.java]: https://github.com/datastax/java-driver/tree/3.0.x/driver-examples/src/main/java/com/datastax/driver/examples/datatypes/Blobs.java
213+
[CASSANDRA-7304]: https://issues.apache.org/jira/browse/CASSANDRA-7304
214+
[Parameters and Binding]: ../manual/statements/prepared/#parameters-and-binding
215+
[Mapper options]: ../manual/object_mapper/using/#mapper-options

0 commit comments

Comments
 (0)