问题
Say I have the following data structure:
{ "name": "i1", "time": 1, "status": 1}
{ "name": "i2", "time": 2, "status": 1}
{ "name": "i3", "time": 3, "status": 1}
{ "name": "i4", "time": 4, "status": 2}
I need to retrieve the item with the largest time and "status" = 1. Then update it's "status" to 2, all this atomically, so the same item can't be retrieved by other consumer in the same time.
Is this possible with rethinkdb ?
回答1:
Since atomicity in RethinkDB is only guaranteed on a per-document level, this is only partially possible.
You can do something like this:
r.table(...)
.orderBy(index=r.desc("time"))
.filter({status: 1})
.limit(1)
.update(r.branch(r.row["status"] == 1, {status: 2}, {}), return_changes=True)
Everything inside of the update
is going to be applied atomically. So in case the status of the entry has already been set to 2 by another client, the query will return {unchanged: 1} and you can run it again until it successfully performs an update.
However it does not guarantee that at the time where the update is done, the selected document is still the one with the largest time. Another client could insert a new document with a larger time while this query was running, which would make the query update the status of the then only second largest document to 2.
For fully protecting against this, you'd need to use an explicit mutex or read/write lock for the table.
来源:https://stackoverflow.com/questions/29368121/rethinkdb-atomic-retrieve-and-update