cassandra-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrew Tolbert <andrew.tolb...@datastax.com>
Subject Re: Consistency when adding data to collections concurrently?
Date Sat, 12 Nov 2016 15:38:54 GMT
You can do it in a SimpleStatement assuming you provide the CQL exactly as
you provided, but in a PreparedStatement it will not work because cql
prohibits provide bind values in collection literals.  For it to work you
could provide a List of UDT values in a bound prepared statement, i.e.:

    UserType udtType =
cluster.getMetadata().getKeyspace("k").getUserType("u");
    UDTValue value = udtType.newValue();
    value.setString(0, "data");

    PreparedStatement p0 = session.prepare("UPDATE my_table SET labels =
labels + ? where id = ?");
    BoundStatement b0 = p0.bind(*Lists.newArrayList(value)*, 0);
    session.execute(b0);

Thanks,
Andy

On Sat, Nov 12, 2016 at 9:02 AM, Ali Akhtar <ali.rac200@gmail.com> wrote:

> Looks like the trick was to use [] around the udt value literal.
>
> Any way to do this using the java driver?
>
> On Sat, Nov 12, 2016 at 7:58 PM, Ali Akhtar <ali.rac200@gmail.com> wrote:
>
>> Changing the double quotes to single quotes gives:
>>
>> UPDATE my_table SET labels = labels + {id: 'foo'} where id = '';
>>
>> InvalidRequest: Error from server: code=2200 [Invalid query]
>> message="Invalid user type literal for labels of type list<frozen<label>>"
>>
>>
>> On Sat, Nov 12, 2016 at 7:50 PM, Ali Akhtar <ali.rac200@gmail.com> wrote:
>>
>>> The question is about appending to a set of frozen<udt> and how to do
>>> that while avoiding the race condition.
>>>
>>> If I run:
>>>
>>>  UPDATE my_table SET labels = labels + {id: "foo"} where id = 'xx';
>>>
>>> I get:
>>>
>>> SyntaxException: line 1:57 no viable alternative at input '}' (...=
>>> labels + {id: ["fo]o"}...)
>>>
>>> Here labels is set<frozen<label>>
>>>
>>> On Sat, Nov 12, 2016 at 7:40 PM, Vladimir Yudovin <vladyu@winguzone.com>
>>> wrote:
>>>
>>>> If I used consistency = ALL both when getting the record, and when
>>>> saving the record, will that avoid the race condition?
>>>> If I use consistency level = all, will that cause it to end up with
>>>> [1,2]?
>>>> No. Even if you have only one host it's possible that two threads first
>>>> both read data and than overwrite existing value one by one.
>>>>
>>>> The list is actually of a list<frozen<my_udt>> and not a text
(I used
>>>> text for simplification, apologies).
>>>> In that case, will updates still merge the list values instead of
>>>> overwriting them?
>>>> Do you mean UPDATE cql operation? Yes, it adds new values to list,
>>>> allowing duplicates.
>>>>
>>>> When setting a new value to a list, C* will do a read-delete-write
>>>> internally e.g. read the current list, remove all its value (by a range
>>>> tombstone) and then write the new list.
>>>> As I mentioned duplicates are allowed in LIST, and as DOC says:
>>>>
>>>> These update operations are implemented internally without any
>>>> read-before-write. Appending and prepending a new element to the list
>>>> writes only the new element.
>>>>
>>>> Only when using index
>>>>
>>>> When you add an element at a particular position, Cassandra reads the
>>>> entire list, and then writes only the updated element. Consequently, adding
>>>> an element at a particular position results in greater latency than
>>>> appending or prefixing an element to a list.
>>>>
>>>>
>>>> Best regards, Vladimir Yudovin,
>>>>
>>>> *Winguzone <https://winguzone.com?from=list> - Hosted Cloud
>>>> CassandraLaunch your cluster in minutes.*
>>>>
>>>>
>>>> ---- On Sat, 12 Nov 2016 07:57:36 -0500*Ali Akhtar
>>>> <ali.rac200@gmail.com <ali.rac200@gmail.com>>* wrote ----
>>>>
>>>> The labels collection is of the type set<frozen<label>> , where
label
>>>> is a udt containing: id, name, description , all text fields.
>>>>
>>>> On Sat, Nov 12, 2016 at 5:54 PM, Ali Akhtar <ali.rac200@gmail.com>
>>>> wrote:
>>>>
>>>> The problem isn't just the update / insert though, right? Don't frozen
>>>> entities get overwritten completely? So if I had [1] [2] being written as
>>>> updates, won't each update overwrite the set completely, so i'll end up
>>>> with either one of them instead of [1,2]?
>>>>
>>>> On Sat, Nov 12, 2016 at 5:50 PM, DuyHai Doan <doanduyhai@gmail.com>
>>>> wrote:
>>>>
>>>> Maybe you should use my Achilles mapper, which does generates UPDATE
>>>> statements on collections and not only INSERT
>>>> Le 12 nov. 2016 13:08, "Ali Akhtar" <ali.rac200@gmail.com> a écrit
:
>>>>
>>>> I am using the Java Cassandra mapper for all of these cases, so my code
>>>> looks like this:
>>>>
>>>> Item myItem = myaccessor.get( itemId );
>>>> Mapper<Item> mapper = mappingManager.create( Item.class );
>>>>
>>>> myItem.labels.add( newLabel );
>>>> mapper.save( myItem );
>>>>
>>>> On Sat, Nov 12, 2016 at 5:06 PM, Ali Akhtar <ali.rac200@gmail.com>
>>>> wrote:
>>>>
>>>> Thanks DuyHai, I will switch to using a set.
>>>>
>>>> But I'm still not sure how to resolve the original question.
>>>>
>>>> - Original labels = []
>>>> - Request 1 arrives with label = 1, and request 2 arrives with label = 2
>>>> - Updates are sent to c* with labels = [1] and labels = [2]
>>>> simultaneously.
>>>>
>>>> What will happen in the above case? Will it cause the labels to end up
>>>> as [1,2] (what I want) or either [1] or [2]?
>>>>
>>>> If I use consistency level = all, will that cause it to end up with
>>>> [1,2]?
>>>>
>>>> On Sat, Nov 12, 2016 at 4:59 PM, DuyHai Doan <doanduyhai@gmail.com>
>>>> wrote:
>>>>
>>>> Don't use list, use set instead. If you need ordering of insertion, use
>>>> a map<timeuuid,text> where timeuuid is generated by the client to guarantee
>>>> insertion order
>>>>
>>>> When setting a new value to a list, C* will do a read-delete-write
>>>> internally e.g. read the current list, remove all its value (by a range
>>>> tombstone) and then write the new list. Please note that prepend & append
>>>> operations on list do not require this read-delete-write and thus performs
>>>> slightly better
>>>>
>>>> On Sat, Nov 12, 2016 at 11:34 AM, Ali Akhtar <ali.rac200@gmail.com>
>>>> wrote:
>>>>
>>>> I have a table where each record contains a list<string> of labels.
>>>>
>>>> I have an endpoint which responds to new labels being added to a record
>>>> by the user.
>>>>
>>>> Consider the following scenario:
>>>>
>>>> - Record X, labels = []
>>>> - User selects 2 labels, clicks a button, and 2 http requests are
>>>> generated.
>>>> - The server receives request for Label 1 and Label 2 at the same time.
>>>> - Both requests see the labels as empty, add 1 label to the collection,
>>>> and send it.
>>>> - Record state as label 1 request sees it: [1], as label 2 sees it: [2]
>>>>
>>>> How will the above conflict be resolved? What can I do so I end up with
>>>> [1, 2] instead of either [1] or [2] after both requests have been processed?
>>>>
>>>>
>>>>
>>>
>>
>

Mime
View raw message