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
Issue seq #3744
Issue seq #3744
Conversation
This is related to #367. |
Hey @matanshukry this PR is impressive! The only doubt is on using the # as prefix. We already use it for RIDs. I see Postgres uses only nextval() function (http://www.postgresql.org/docs/8.1/static/sql-createsequence.html), while MySQL seems to have no control over sequences, but rather you can use them in schema only (auto-increment columns). Oracle has both currval and nextval functions, but not as functions (http://docs.oracle.com/cd/B28359_01/server.111/b28286/pseudocolumns002.htm#SQLRF51138) and no prefix for them. |
@luigidellaquila WDYT about the syntax? |
I didn't go through all the code, but I wonder if it's possible to do insert into Foo (a, b) values (#mySequence.next(), 'bar') I don't like the # sign very much, but it does not create problems in terms Luigi 2015-03-11 1:23 GMT+01:00 Luca Garulli notifications@github.com:
|
we may need an integration with the distributed as wel, or declare that this feature is on single node mode, but sounds limitating by the way ipressive ;) |
I like also the @matanshukry's idea about the
Well, node.js propose also |
Created a new issue for that: #3749 |
luigidellaquila - Actually I forgot about the RID syntax. We may be able to distinguish between the two, but I really prefer to avoid inserting the sequence test into the 'from'(field) test. Using a one sign prefix is better than trying to test the string. Also, a prefix isn't a bad way to go. In my opinion choosing a better prefix sign is the preferred choice. |
@matanshukry The usage of # in OrientDB is associated to RIDs. We can use something else. Some proposals: (1) "sequence:" as prefix:
We already support the prefix: (2) Just rely on functions, like other RDBMSs:
|
Not a big fan of global functions. Any chance we can use seq prefix instead?
|
something like: but i think can be tricky the implementation of the 'next' in this way, the case of the 'current' is fine. WDYT ? |
Hey @matanshukry we'd like to release tomorrow 2.1-rc1. What's the status of your contrib? WDYT about the syntax for retrieve the next/current? |
I like the syntax, and I can change it in a few days. But I don't think we should release sequences until we can verify they work correctly. As I wrote (in my long post, I admit), the distributed test is not working. And until it is resolved (or a good explanation on simply how to use it), I don't think we should use sequences. I will change the syntax in a few days anyway though, so you'll be able to merge it if you want (probably later than 2.1-rc1 by now, but still) but my recommendation would be not to use it until the test is resolved. That said, I would love if anyone else can take a look at the test, perhaps I'm not using the classes correctly (I tried many ways so I doubt it, but who knows), or even shed some light on the case. |
@matanshukry Which is the test that failed and need our help? |
@lvca - it's the distributed test ( ServerClusterLocalSequenceTest ) |
I have just run ServerClusterLocalSequenceTest and pass. |
I forgot I added a variable to skip it; Change the variable "RUN_PARALLEL_SYNC_TEST" to true, and run again (Assuming you didn't change it before ?) |
ok, found the distributed problem: when node 1 says version 5 and node 2 says version 6, this is a OConcurrentModificationException, but it's raised an ODistributedException. I changed the code to catch this case and seems to finish correctly. The only weird thing is that 50% of the times the result is not 200 numbers but 197 or 198. Seems some sequenced number is retrieved on both thread. On high contention the number of retry (10) was too low. Just to demonstrate the problem I increased it to 1000, just for test. I've also merged your PR 3738 and pushed everything on "pr/3744" branch. Do you have time to look why the same sequence number is returned to 2 threads? |
I remember working intensively for a day or two trying to find out, and the only reason I could think of is the missing case of distributed locks. I can't say for sure if the problem was between different nodes by the way, and not the local node. The fact that the local node also gets an update message after updating a document, might be problematic too. I could test the theory by creating some sort of distributed lock (or perhaps higher scope lock for the local node) and test it, but my time is a bit short now. I can't promise anything less than two weeks. |
After looking at the code a bit, I agree with tlgman about the implementation; Making next() work in such a case is a bit tricky. Any chance we can use select sequence:.next() or something like that (the idea is using the entire syntax is in the select clause, rather than the from clause) ? |
@luigidellaquila WDYT about the syntax? |
I have good news on this. The concurrent sequence in a cluster is semantically correct. The problem is the high contention + replication + MVCC that practically let fail it. The test passes if:
OSequence seq = db.getMetadata().getSequenceLibrary().getSequence(sequenceName);
for (int j = 0; j < SEQ_RUN_COUNT; ++j) {
try {
long value = seq.next();
res.add(value);
Thread.sleep(new Random().nextInt(20));
} catch (OConcurrentModificationException ex) {
failures.incrementAndGet();
}
}
I published it as "sequence" branch. |
I think on this use case it would be much faster and cheap acquiring a distributed lock to avoid contentions. OrientDB provides it by OHazelcastPlugin.getLock(name) where name could be the following "sequence..". In this way it would be unique even in case of multiple DBs. If you can get a Distributed lock, acquire it, do the change and then release it, you switch from optimistic approach (MVCC) to a pessimistic one. WDYT about providing this behavior as a setting? |
That could be a good feature, but I feel like the optimistic approach (MVCC) should work. Although your changes to the code would work, I see no reason why we need to add a pause to make it work; It sound like an internal flaw. I tried increasing the internal try and catching it too, by the way; it wasn't enough. |
Conflicts: core/src/main/java/com/orientechnologies/orient/core/db/document/ODatabaseDocumentTx.java core/src/main/java/com/orientechnologies/orient/core/metadata/OMetadataDefault.java tools/src/main/java/com/orientechnologies/orient/console/OConsoleDatabaseApp.java
Hey guys, I'm going to test this PR if distributed stuff is working now, but we didn't resolve the problem about syntax. I think the smoothest integration would be creating a new "sequence" target and execute this kind of query: select next() from sequence:InvoiceId So if you want it in your update you can do: update invoice set id = (select next() from sequence:InvoiceId), date = date() |
User perspective
Usage
Create a sequence
Sequence types:
Drop a sequence
Using a sequence
Possible functions:
Notes
Prefix
I decided to use the hash sign(#) prefix for sequences, although that is easy to replace. The reason to use any sign was due to code architecture, however in my opinion it is also the better option; When not using any prefix, it can collide with table columns.
Distributed
Distributed sequences are not 100% working now. They will most probably work, just be careful not to use them too much (although i'm hoping we can finish the work with distributed sequences until the next release).
Code perspective
Test
I added two test cases:
** Ordered sequence: check two ordered sequence, under simple load, will generate ordered values.
** Cached sequence: Check two cached sequences, with a specific cache value, will generate values with
range same as cache value (showing that one of the sequences cached a range of values)
* Parallel Sync: Attempt to create multiple (2) threads, where each thread will use a different node (and databases, as according to multi-threading rules in orientdb), and generate unique N(100) values, each. The result should be 2N(200) unique values.
Notes:
In order to pass the test though, it has a flag which is set to false, hence not testing this specific test (parallel sync) at all.
I am not entirely sure what the problem is, but there seem to be more than one:
Although the distributed part of sequences is not complete, I decided to still open this PR in case someone more experienced with the project might shed some light on the distributed errors.