-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
models/issue.go NewIssue() could fail due to duplicate key #7887
Comments
So a mutex would actually be at the wrong level - it needs to be at the DB level (Consider clusters). There's only really three options to fix it:
I think option 1 is probably a reasonable thing to do, but someone with more specific DB knowledge could look into how much work it would be to add 2 or 3 - but I think you still need retries when I last looked into this. |
If we want finish that on DB level, it's a complex SQL and specific for different databases. So I think the simple and dirty method is just retry it 3 times if it failed because of exist issue number. |
Ultimately, I would like to consider dropping the |
|
Unfortunately, it won't. Consider the following scenario: By the time T2 inserts the row in I realized this when I created the stress test in #8005. It will always fail with this kind of method, unless we use some method of serialization like a semaphore or a lock in the table. But the semaphore will not scale in a multi-server setup as you've pointed out, and a database lock (either at row or table level) is dangerous because it's very easy to end up with a deadlock. That's why I gave up and went for the retry route. |
The current code for
models/issue.go
roughly does:It's possible that under heavy loads (e.g. a small server) two sessions may attempt to use the same index number to create issues; one of the two will fail due to a race condition:
issue.go
, in the context of user A's request,getMaxIndexOfIssue()
returns99
. It will be used at step 5.issue.go
, in the context of user B's request,getMaxIndexOfIssue()
also returns99
. because at the moment that's the latest issue for the repo. It will be used at step 6.issue.go
, in the context of user A's request,newIssue()
inserts A's issue withIndex: 100
.issue.go
, in the context of user B's request,newIssue()
attempts to insert B's issue withIndex: 100
and fails withduplicate key error
, because100
was used at step 5.This will of course depend on the database locking model.
I think the best way to handle this is to use a mutex, thus covering most scenarios.
The text was updated successfully, but these errors were encountered: