Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot update the record because the version is not the latest #1312

Closed
honnix opened this issue Jan 28, 2013 · 47 comments
Closed

Cannot update the record because the version is not the latest #1312

honnix opened this issue Jan 28, 2013 · 47 comments
Assignees
Milestone

Comments

@honnix
Copy link

honnix commented Jan 28, 2013

Hi,

This is probably a very old question, but slightly different in my case and haven't found answer in group, so post it again.

Following is my code snippet.

  1. With blueprints
    @Test
    public void testTransaction() {
        OrientGraph graph = new OrientGraph("remote:localhost/tmp", "admin", "admin");

        Vertex a = null;
        try {
            a = graph.addVertex(null);
            graph.stopTransaction(TransactionalGraph.Conclusion.SUCCESS);
        } catch (Exception e) {
            graph.stopTransaction(TransactionalGraph.Conclusion.FAILURE);
            e.printStackTrace();
        }

        try {
            for (int i = 0; i < 100; ++i) {
                graph.addEdge(null, graph.addVertex(null), a, "");
            }
            graph.stopTransaction(TransactionalGraph.Conclusion.SUCCESS);
        } catch (Exception e) {
            graph.stopTransaction(TransactionalGraph.Conclusion.FAILURE);
            e.printStackTrace();
        }

        try {
            Vertex b = graph.addVertex(null);
            graph.addEdge(null, b, a, "");
            graph.stopTransaction(TransactionalGraph.Conclusion.SUCCESS);
        } catch (Exception e) {
            graph.stopTransaction(TransactionalGraph.Conclusion.FAILURE);
            e.printStackTrace();
        } finally {
            graph.shutdown();
        }
    }
  1. Without blueprints
    @Test
    public void testTransactionNative() {
        OGraphDatabase db = new OGraphDatabase("remote:localhost/tmp");
        db.open("admin", "admin");

        ODocument a = null;
        try {
            db.begin(OTransaction.TXTYPE.OPTIMISTIC);

            a = db.createVertex().save();

            db.commit();
        } catch (Exception e) {
            db.rollback();
            e.printStackTrace();
        }

        try {
            db.begin(OTransaction.TXTYPE.OPTIMISTIC);

            for (int i = 0; i < 100; ++i) {
                db.createEdge(db.createVertex().save(), a.save()).save();
            }

            db.commit();
        } catch (Exception e) {
            db.rollback();
            e.printStackTrace();
        }

        try {
            db.begin(OTransaction.TXTYPE.OPTIMISTIC);

            db.createEdge(db.createVertex().save(), a.save()).save();

            db.commit();
        } catch (Exception e) {
            db.rollback();
            e.printStackTrace();
        } finally {
            db.close();
        }
    }

Both versions I will get exception when committing the third transaction like: om.orientechnologies.orient.core.exception.OConcurrentModificationException: Cannot UPDATE the record #7:4 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v2 your=v1)

The problem here is "a" actually, when I create the edge, if I try to "save" it again, then I will get the above exception; while if not, everything is fine.

But in blueprints, "a" will always be saved:

public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
        // ...

        // SAVE THE VERTICES TO ASSURE THEY ARE IN TX
        db.save(((OrientVertex) outVertex).getRawElement());
        db.save(((OrientVertex) inVertex).getRawElement());
        edge.save();
        return edge;
    }

I've tried to disable level1 and level2 cache, and disable mvcc, but nothing works.

How can I solve this problem? Or is it not expected to use a vertex/edge created in another transaction?

@lvca
Copy link
Member

lvca commented Jan 30, 2013

Fixed in commit 009dd87

@lvca lvca closed this as completed Jan 30, 2013
@dashingsat
Copy link

Hi Luca,

I am using 2.M1 and I have started getting the above mentioned error. I was not getting this error when I was using version 1.7.7

Please let me know if you are going to fix it ..

@kataik
Copy link

kataik commented Aug 17, 2015

Hi Luca,
same here. I've checked and the version number is the latest.

@pressyfdo
Copy link

I am getting the same error in orientdb-community-2.1.5.

Please try to fix it as soon as possible because we have planned to use it in production.

@StarpTech
Copy link

Sometimes I got the same error in Studio but I can't reproduce it.

@lvca
Copy link
Member

lvca commented Nov 26, 2015

Hi, OrientDB supports optimistic transactions. Look at: http://orientdb.com/docs/last/Concurrency.html#atomic-operations

@lvca
Copy link
Member

lvca commented Jan 21, 2016

Closed in 2.1.9.

@lvca lvca closed this as completed Jan 21, 2016
@lvca lvca added bug and removed question labels Jan 21, 2016
@lvca lvca modified the milestones: 2.1.x (next hotfix), 2.1.10 Feb 2, 2016
@varuntahin001
Copy link

Hello Guys,

We are using version orientdb-community-2.1.10 and facing the similar issue . Please let us know in which version this bug is fixed or is still existing.

@andrii0lomakin
Copy link
Member

@varuntahin001 why do you think that that is a bug ?

@varuntahin001
Copy link

While deleting and adding edge we are having similar issue as the graph is taking previous vertex in cache and it is throwing Cannot update the record because the version is not the latest.
So the version of vertex is not upgrading and it is taking vertex from cache.
We tried clearing the local cache before reading the vertex and retry logic to avoid this and OConcurrentModificationException. But this logic seems inconsistent , it happens sometimes, while not the other times.

We have also tried with global setting OGlobalConfiguration.CACHE_LOCAL_ENABLED.setValue(false);

As above discussions are happening I was curious as this might be issue with the previous versions , as comment states hotfix for this in 2.1.10

@andrii0lomakin
Copy link
Member

@varuntahin001 sorry for asking but did you try to use latest version , a lot of issues were fixed since 2.1.10 ?

@saeedtabrizi
Copy link
Contributor

Hi @Laa
i have similar error in odb 2.2.13 .

Cannot UPDATE the record #17:9 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v763 your=v762)
	DB name="Putin_DB"

when i try some update on a record i got this error !

@andrii0lomakin
Copy link
Member

Hi @saeedtabrizi , why do you think that this error is incorrect ?

@saeedtabrizi
Copy link
Contributor

@Laa this error is correct but i need to remove all async update operation from my app to handle this issue . i think all users confused because there is lack of documentation about CRUD operation (such as our scenario for parallel updating ) in ODB.
i suggest write more documentation about versioning of records in ODB .
Thanks

@StarpTech
Copy link

StarpTech commented Dec 14, 2016

@saeedtabrizi @Laa I think the problem is that orientdb use OCC instead MVCC or a MIX of both.
There are MVCC in transactions but the strategy looks very chaotic because orientdb says:

For this reason, you need to code your applications to be concurrency-proof.
Reference: http://orientdb.com/docs/2.1/Concurrency.html#transactions

I think I speak to lots of developers when I say thats some of a reason why I use a database is because I dont want to care about such issues. MVCC was created to prevent locking. If orientdb throws an excepction and breaks my operation it shows that MVCC is not implemented correctly.

Use of retry, locking or other mechanism is just "plug holes". In my opinion the whole strategy of concurrency should be reviewed and standardized.

Very good paper: http://guide.couchdb.org/draft/consistency.html

@smolinari
Copy link
Contributor

smolinari commented Dec 15, 2016

Do you mean

-attempt update - get error "you have stale data" - refresh local copy - retry update

??

That is what I understood MVCC was too.

Scott

@StarpTech
Copy link

For better understanding http://guide.couchdb.org/draft/consistency.html#locking

@smolinari
Copy link
Contributor

Which part of that document is ODB not following?

Scott

@smolinari
Copy link
Contributor

smolinari commented Dec 15, 2016

In fact, that doc explains the "recovering from the (stale data) error is easy from an applicatin perspective", which is normal for such a system.

Recovering from this error is easy to accomplish from an application perspective. Just download CouchDB’s version of the playlist and provide an opportunity to merge the changes or save local modifications into a new playlist.

Like I said. 😄

attempt update - get error "you have stale data" - refresh local copy - retry update

Scott

@StarpTech
Copy link

StarpTech commented Dec 15, 2016

@smolinari What's your point?

@smolinari
Copy link
Contributor

What's your point?

That ODB works just like Couchdb in terms of concurrency. If an update to a record happens before another, then the later update will fail, because that version is old/ stale. At that point, the newer record must be retrieved and it must be changed and attempted to update again. That is how MVCC works. It doesn't ensure a proper is update is made between to updating clients. It ensures an improper update won't be made (i.e with stale data).

Scott

@StarpTech
Copy link

StarpTech commented Dec 15, 2016

Yes, that's correct like GIT. But its not up to the developer to solve this conflict.

This issue should be solved by setting the "conflict strategy" to e.g content or auto merge right?

Cannot UPDATE the record #17:9 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v763 your=v762)
	DB name="Putin_DB"

but I don't understand the part

For this reason, you need to code your applications to be concurrency-proof.

when orientdb use MVCC under the hood.

Update: Orientdb use optimistic concurrency when transactions are commited. This is correct and the case where the developer has to handle concurrency errors.

@smolinari
Copy link
Contributor

What conflict strategy are you looking for?

Scott

@StarpTech
Copy link

StarpTech commented Dec 15, 2016

Its off topic but a way where I dont have to care about transactions conficts. Setting a default conflict strategy like in MVCC I only know the retry statement commit retry 100. I can also LOCK every record but this is not elegant and is only supported in Memory only databases therefore useless.
#1677 the issue is 3 years old 👎

@StarpTech
Copy link

StarpTech commented Dec 15, 2016

@smolinari Imagine you use orientdb with lots of clients and high-traffic. All clients starts transactions in any kind of size (orientdb recommend small transactions because of concurrency issues) what happens? You will run into lots of concurrency issues which you have to solve with a retry logic but the end is not in sight because you need a magical retry number??? I dont get the picture of that concept and I can't imagine that all other database vendors goes with the same approach.

@StarpTech
Copy link

StarpTech commented Dec 15, 2016

After some research I came to this. I think this is what orientdb needs.

Transaction priorities

BEGIN PRIORITY <LOW | NORMAL | HIGH>;

When two transactions contend for the same resource, the one with the lower priority loses and is retried. On retry, the transaction inherits the priority of the winner. This means that each retry makes a transaction stronger and more likely to succeed.

https://www.cockroachlabs.com/docs/transactions.html#transaction-priorities
Isolation levels

BEGIN ISOLATION LEVEL <SERIALIZABLE | SNAPSHOT>;

Unlike SNAPSHOT, SERIALIZABLE isolation permits no anomalies. However, due to CockroachDB’s transaction model, SERIALIZABLE isolation may require more transaction restarts, especially in the presence of high contention between concurrent transactions. Consider using SNAPSHOT isolation for high contention workloads.

Orientdb use SERIALIZABLE
https://www.cockroachlabs.com/docs/transactions.html#isolation-levels

@smolinari
Copy link
Contributor

smolinari commented Dec 15, 2016

As far as I can tell, ODB offers serializable isolation and they want to switch to something more like snapshotting (possibly).

#6013

I have no idea how transaction contention priority should work and seems like it isn't needed, with ODBs OCC system. There are no locks in ODB's transaction system.

I also think the ODB docs on the transaction system is a bit misleading.

This sentence is correct:

Optimistic concurrency requires that you retire the transaction in the event of conflicts.

So, this part of the code with the retries is basically incorrect.

     catch( OConcurrentModificationException e ) {
          // SOMEONE HAS UPDATED THE INVOICE VERTEX
          // AT THE SAME TIME, RETRY IT
     }

There can be no retry, because every retry will fail. The data is stale. As the sentence above states "retire the transaction", you'd have to go to the user and let them know their update failed, ask them to refresh the page and try again (in a web app) i.e. the conflict is resolved by the user.

So, if there are scenarios where retries will work and will get the transaction to commit, those scenarios aren't clarified in the docs. From what I am reading, only stale data (version conflicts) would be the reason for transactions or non-transactional updates to fail, which means you must resolve the conflict and that means getting the fresh version, making the changes again and saving.

Scott

@linxd
Copy link

linxd commented Mar 22, 2017

2.2.17 also got this error

Failed to update an entity: Cannot UPDATE the record #7:1 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v2 your=v1)

@easy2coderep
Copy link

Got the same error in 2.2.19.

com.orientechnologies.orient.core.exception.OConcurrentModificationException: Cannot UPDATE the record #18:25457 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v2 your=v1)

@andrii0lomakin
Copy link
Member

@easy2coderep why do you think this is an error ?

@andrii0lomakin
Copy link
Member

I mean that is typical behaviour if the same record is updated from two different clients

@easy2coderep
Copy link

@Laa I am quite sure that there is single instance is performing the update operations sequentially. So if there is any such instance where the record which is accessed by first client, is been modified by another client then better to print the stacktrace of first client with warning message.

It would be more meaningful and users may need not be scaring of this exception.

@andrii0lomakin
Copy link
Member

@easy2coderep sorry I do not understand you. You are quite sure that you make only sequential requests? According to your question update from the first client is already happened so we can not print a stack trace from the first client.

@zeeshan2709
Copy link

@Laa : i came across the same issue and found i this thread.
Do you think ODB is good to be used in a system where data contention is frequent and the order the data is also important?

@andrii0lomakin
Copy link
Member

andrii0lomakin commented Jul 7, 2017

@zeeshan2709 what do you mean? Sorry, I do not understand a question, could you provide an example or make question more clear?

@erik-megarad
Copy link

I'm getting this same error in 2.2.25. Using the RETRY clause of CREATE VERTEX doesn't do anything, apparently. I'm not sure why that clause exists if it doesn't work in this case.

Apparently, every time I create a vertex I have to code my application to catch these errors and retry. That's a really dumb burden to place on the developers, and reflects very poorly on the maturity and sophistication of OrientDB.

@andrii0lomakin
Copy link
Member

Hi @subwindow it can not be thrown during creation of vertexes only during an update, are you sure that you do not create any edges along with vertexes for example?

@andrii0lomakin
Copy link
Member

@subwindow could you provide SQL which you use to create records together with retry?

@lightjiao
Copy link

Hi @Laa ,I have this same question.
I use HTTP RESTful API to execute sqlbatch, and I get this error

{
    "code": 409,
    "reason": 409,
    "content": "com.orientechnologies.orient.core.exception.OConcurrentModificationException: Cannot UPDATE the record #64:0 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v15 your=v14)\r\n\tDB name=\"xxxxx\""
}

Here is my request

curl -X POST \
  http://192.168.100.16:2480/batch/xxx_database_xxxx \
  -H 'accept-encoding: gzip,deflate' \
  -H 'authorization: Basic  YWRtaW46YWRtaW4=' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'postman-token: c7d4e5a0-9c15-d7e1-0830-6233b7069e8c' \
  -d '{
    "transaction": true,
    "operations": [
        {
            "type": "script",
            "language": "sql",
            "script": [
                "begin;  UPDATE v_xxxxxx CONTENT {\"name\":\"wewqe\",\"instanceId\":\"59aa0a0c378e4\",\"creator\":\"yonghuA\",\"ctime\":\"2017-09-02 09:31:56\"} UPSERT WHERE instanceId = '\''59aa0a0c378e4'\''; UPDATE v_xxxxxx CONTENT {\"name\":\"\u6743\u9650\u6d4b\u8bd5\",\"instanceId\":\"59aa0a1865632\",\"creator\":\"yonghuA\",\"ctime\":\"2017-09-02 09:32:08\"} UPSERT WHERE instanceId = '\''59aa0a1865632'\''; commit;"
            ]
        }
    ]
}'

The data were desensitized

This problem is difficult to reproduce, and can I use RETRY to solve this problem?

@jpstrikesback
Copy link

jpstrikesback commented Oct 21, 2017

Was also experiencing this it seems because of an embedded doc with the @type flag set:

#3779 (comment)

I am able to reproduce this reliably

@MehdiFal
Copy link

MehdiFal commented Jan 8, 2018

I get the same error on OrientDB 2.2.0

There's no concurrency in my case. Only 1 client performing the update. (through postman)

At first I thought the record got locked for some reason, so to be sure, I recreated the whole DB. So I performed a new test, Insert record then update it. Same thing happened.

It was happening randomly at first, but now, it does happen on every update.

"Cannot UPDATE the record #18:0 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v5 your=v4)\r\n\tDB name=\"mydb\"\r\n\tDB name=\"mydb\""

In which version has this been fixed?

Thanks.

@smolinari
Copy link
Contributor

There is nothing to fix. ODB works correctly. Check your setup and what you are doing. You more then likely have some sort of error in your thinking, data or logic.

Scott

@Tushavi
Copy link

Tushavi commented Jul 10, 2018

I am having a similar error. I am using orientDB-tp3-3.0.2 and gremlin_python to connect to orientdb and run queries.
I open a thread from the python application (only 1 thread), it runs all gremlin queries sequentially.

Right now I am testing with 3 vertices and 2 edges creation. I successfully create the 3 vertices and am able to create the first edge. The second edge creation throws the error :
500: Cannot UPDATE the record #23:8 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v2 your=v1)

I also get a similar error when I try to drop the graph.
I use :
> g.E().drop().iterate() - works fine
> g.V().drop().iterate() - throws error
> g.V().drop().iterate() - works fine after a few tries and after trying some other queries in between

@wolf4ood
Copy link
Member

Hi @Tushavi

see this. orientechnologies/orientdb-gremlin#148

It should be solved in the next OrientDB 3.04 release

@Tushavi
Copy link

Tushavi commented Jul 13, 2018

Hi @maggiolo00 ,
I upgraded the version to 3.04, it works way better now. There are very infrequent instances, when i get the same error, but the gremlin requests are not freezing now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests