Optimistic Concurrency
Optimistic concurrency control is a Solr NoSQL feature that allows a conditional update based on document _version_
. Using optimistic concurrency normally involves the following READ-MODIFY-WRITE process:
- client reads a document
- client changes the document locally
- client resubmits the changed document to solr
- go back to step 1 if step 3 fails with HTTP error code 409 (version conflict)
For simple field updates or modifications, see Atomic Updates
Versioning
Solr automatically adds a _version_
field to all documents. A client can specify a value for _version_
on any update to invoke optimistic concurrency control.
The following table summarizes the semantics of specifying _version_
for an update:
_version_ | semantics |
---|---|
> 1 | Document version must exactly match |
1 | Document must exist |
< 0 | Document must not exist |
0 | Don’t care (normal overwrite if exists) |
Specifying version on an update
For an add, it’s easiest to simply specify _version_
by adding it as a field in the document along with the other fields (see the Example below).
It’s also possible to specify _version_
as a request parameter in the URL:
$ curl http://localhost:8983/solr/update?_version_=7 -H 'Content-type:application/json' -d '[{"id":"smalldoc"}]'
Delete operations with optimistic concurrency currently need to use the URL method to specify _version_
.
Optimistic Concurrency Example
First, let’s add a document representing a book:
$ curl http://localhost:8983/solr/update -H 'Content-type:application/json' -d ' [ {"id":"book1", "title":"Neuromancer","author":"William Gibson", "copiesIn_i":7, "copiesOut_i":3 } ]'
Now let’s pretend that someone is checking out a copy and we want to decrement copiesIn and increment copiesOut. First we retrieve the latest version of the document with real-time get:
$ curl http://localhost:8983/solr/get?id=book1
{ "doc": { "id":"book1", "title":["Neuromancer"], "author":"William Gibson", "copiesIn_i":7, "copiesOut_i":3, "_version_":1408813562908901376}}
Now we will modify the document fields and send it back to Solr (making sure we did *not* modify the _version_
field):
curl http://localhost:8983/solr/update -H 'Content-type:application/json' -d ' [ { "id":"book1", "title":["Neuromancer"], "author":"William Gibson", "copiesIn_i":6, "copiesOut_i":4, "_version_":1408813562908901376} ]'
The presence of the _version_
field instructs Solr to accept the update only if the document version matches exactly. After the update has successfully completed, the document will have a new _version_
that is guaranteed to be higher than the last.
curl http://localhost:8983/solr/get?id=book1
{ "doc": { "id":"book1", "title":["Neuromancer"], "author":"William Gibson", "copiesIn_i":6, "copiesOut_i":4, "_version_":1408814192853516288}}
Of course this was just an example, and we could have used Solr’s Atomic Update feature to do this much easier.
Example Failure
If the client specifies a _version_
that does not match what currently exists in Solr, an HTTP error with code 409 (Conflict) will be returned.
$ curl -i http://localhost:8983/solr/update -H 'Content-type:application/json' -d ' [{"id":"book1", "author":"Mr Bean", "_version_":12345}]'
HTTP/1.1 409 Conflict Content-Type: text/plain;charset=UTF-8 Transfer-Encoding: chunked { "responseHeader":{ "status":409, "QTime":1}, "error":{ "msg":"version conflict for book1 expected=12345 actual=1408814192853516288", "code":409}}
Note that we used the curl option -i
to show the response HTTP headers to verify that this generated an HTTP-level error in addition to the Solr-level error in the body of the response.