@@ -157,4 +157,59 @@ and we've had many reports where the problem turned out to be in user code.
157157
158158See [ 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