-
-
Notifications
You must be signed in to change notification settings - Fork 218
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
Fix #7783: Deadlock during index creation when parallel workers are used #8163
base: master
Are you sure you want to change the base?
Fix #7783: Deadlock during index creation when parallel workers are used #8163
Conversation
…rkers are used Deadlock is possible when index deletion and creation are performed in the same transaction and a deleted index is used by a computed field expression. Each worker attachment loads table's metadata, parses the expression and tries to get SR lock on the deleted index. They will never get it because the main thread holds EX lock and waits for worker attachments to complete. The solution is to prevent the optimizer from using deleted indexes by making an attempt to get SR lock with NO_WAIT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few more questions:
- if
compileRelation()
called more than once for the single query - how many timesidl_count
will be incremented ? - if statement was prepared while index is dropping (as shown in Deadlock during index creation when parallel workers are used #7783) - could it use new index instance after it will be created ? Note, statement could be cached in statements cache or in SP\triggers cache
} | ||
} | ||
// No need to lock the index here because it is already | ||
// locked by Optimizer::compileRelation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment is good, but assert will not harm, imho
|
||
if (idx_lock) | ||
{ | ||
if (idx_lock->idl_count == 1 && idx_lock->idl_lock->lck_logical == LCK_EX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that idl_count > 1
?
I.e. perhaps it should check for idl_count > 0
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like currently LCK_EX
is possible only with idl_count == 1
. Should I correct it to idl_count > 0
to make it more safe (maybe for future changes)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, do it, please. It makes no harm but protect us from "impossible" cases ;)
Also, consider to add assert, if you sure it is really impossible.
I tested it. If |
|
You are right. And allowing duplicates in the resource list is not a good idea, I guess. |
I see 2 ways to fix this problem:
Which one is better? I like the second one more. |
Note comment in
It become more complex than it looks |
I tried a solution where |
Deadlock is possible when index deletion and creation are performed in the same transaction and a deleted index is used by a computed field expression. Each worker attachment loads table's metadata, parses the expression and tries to get SR lock on the deleted index. They will never get it because the main thread holds EX lock and waits for worker attachments to complete. The solution is to prevent the optimizer from using deleted indexes by making an attempt to get SR lock with NO_WAIT.