> Given atomicity is not possible, it is ok for a brief period of
> inconsistency but I cannot afford permanent inconsistency for even a
> single successful or timed-out write.
Even when using a strongly consistent CL level you may still get logical 
inconsistencies if your batch_mutation fails with a TimedOut. All we know in 
the face of a TimedOut is that the coordinator thought there was enough UP 
nodes to start the request, but less than CL nodes responded in time for *all* 
the rows in the request. 

In your example (user + state CF's) it sounds like the State CF is a custom 
secondary index. Can you make one batch_mutate to write the user, and then 
another to write the state CF once you know the user is stored. Or make a 
single batch_mutation call and have code the works with the state CF handle 
missing users ? 

> I would guess this is general enough use case. How is this accomplished ?
> Do I write to a third CF, say the 'LOG CF' with PREPARING status as
> first batch. 

http://www.slideshare.net/mattdennis/cassandra-nyc-2011-data-modeling

This may also be interest as background 
Life beyond Distributed Transactions: an Apostate’s Opinion
http://www.ics.uci.edu/~cs223/papers/cidr07p15.pdf

Cheers

-----------------
Aaron Morton
Freelance Developer
@aaronmorton
http://www.thelastpickle.com

On 16/03/2012, at 4:23 AM, A J wrote:

> ok ..... disappointing. You could have got atomicity like behavior
> most of the time, if it was otherwise.
> 
> How does one execute a logical write that is spread in several CFs
> (say in User CF, you have 'state' as a column and userid as rowkey.
> But in State CF, you have state as rowkey and userid as a column)
> Given atomicity is not possible, it is ok for a brief period of
> inconsistency but I cannot afford permanent inconsistency for even a
> single successful or timed-out write.
> I cannot ever have a userid in the UserCF that is not in the state CF
> or vice-versa except for a very small fraction of writes and that too
> for only a few minutes at max. Writing to the state CF has to be
> almost always synchronous with write to User CF.
> 
> I would guess this is general enough use case. How is this accomplished ?
> Do I write to a third CF, say the 'LOG CF' with PREPARING status as
> first batch. Then the second batch, which is conditional on 1st batch
> being successful writes to the main User and State CFs. Then the third
> batch, which is conditional on 2nd batch being successful updates the
> PREPARING flag to COMPLETED flag in the LOG CF ?
> I also run a standalone job every few minutes that takes PREPARING
> records from the LOG CF older than some interval and apply them to the
> main CFs and change its status.
> 
> This approach may not be performant but could not think of anything
> else. Appreciate any ideas.
> 
> Thanks
> 
> 
> 
> On Thu, Mar 15, 2012 at 5:22 AM, aaron morton <aa...@thelastpickle.com> wrote:
>> The simple thing to say is: If you send a batch_mutate the order which the
>> rows are written is undefined. So you should not make any assumptions such
>> as if rows C is stored, rows A and B also have.
>> 
>> They may do but AFAIK it is not part of the API contract.
>> 
>> For the thrift API batch_mutate takes a Map of mutations keyed on the row
>> key. CQL builds a list of row mutations in the same order as the statement.
>> 
>> Even if they are in a list there is no guarantee they will be processed in
>> that order.
>> 
>> If you get a timed out error all you know is the mutation, as a whole, was
>> applied of < CL nodes.
>> 
>> Cheers
>> 
>> -----------------
>> Aaron Morton
>> Freelance Developer
>> @aaronmorton
>> http://www.thelastpickle.com
>> 
>> On 15/03/2012, at 1:22 PM, Tyler Hobbs wrote:
>> 
>> Ah, my mistake, you are correct. Not sure why I had forgotten that.
>> 
>> The pycassa docs are slightly wrong there, though.  It's technically atomic
>> for the same key across multiple column families.  I'll get that fixed.
>> 
>> On Wed, Mar 14, 2012 at 5:22 PM, A J <s5a...@gmail.com> wrote:
>>> 
>>>> No, batch_mutate() is an atomic operation.  When a node locally applies
>>>> a batch mutation, either all of the changes are applied or none of them
>>>> are.<
>>> The steps in my batch are not confined to a single CF, nor to a single
>>> key.
>>> 
>>> The documentation says:
>>> datastax:
>>> Column updates are only considered atomic within a given record (row).
>>> 
>>> Pycassa.batch:
>>> This interface does not implement atomic operations across column
>>> families. All the limitations of the batch_mutate Thrift API call
>>> applies. Remember, a mutation in Cassandra is always atomic per key
>>> per column family only.
>>> 
>>> 
>>> On Wed, Mar 14, 2012 at 4:15 PM, Tyler Hobbs <ty...@datastax.com> wrote:
>>>> On Wed, Mar 14, 2012 at 11:50 AM, A J <s5a...@gmail.com> wrote:
>>>>> 
>>>>> 
>>>>> Are you saying the way 'batch mutate' is coded, the order of writes in
>>>>> the batch does not mean anything ? You can ask the batch to do A,B,C
>>>>> and then D in sequence; but sometimes Cassandra can end up applying
>>>>> just C and A,B (and D) may still not be applied ?
>>>> 
>>>> 
>>>> No, batch_mutate() is an atomic operation.  When a node locally applies
>>>> a
>>>> batch mutation, either all of the changes are applied or none of them
>>>> are.
>>>> 
>>>> Aaron was referring to the possibility that one of the replicas received
>>>> the
>>>> batch_mutate, but the other replicas did not.
>>>> 
>>>> --
>>>> Tyler Hobbs
>>>> DataStax
>>>> 
>> 
>> 
>> 
>> 
>> --
>> Tyler Hobbs
>> DataStax
>> 
>> 

Reply via email to