-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Support or disallow named locks #3631
Comments
Regarding connection pinning at the vtgate level, getting correct behavior would requiring sometimes establishing establishing as well as maintaining vttablet session without necessarily starting or being inside a transaction. I'm not sure if vtgate or vttablet make any assumptions that would make it hard to separate the concept of a session from the concept of a transaction (aside from the current behavior of recycling your session at the vtgate level on every commit or between executing statements outside of a transaction). |
For reference, the functionality for mysql's There are a few problems with this functionality that we need to address:
In light of the above behaviors, I think it will be better to implement this function in vitess from the ground up instead of relying on mysql. Here's the proposal: The core functionality of get_lock will be implemented by vttablet. The functionality will be more akin to a traditional mutex. It will have the following properties:
To obtain a vitess-wide lock, you can issue a Any other usage of ImplementationVTGate does not need to change. Here are the changes for vttablet: Planbuilder
ExecutionBuild a
The state changes of the |
While running some tests, I realized that I misunderstood the timeout parameter: it only specifies how long to wait for a lock. It does not mean that the lock is held for that long. So, I'm going to make some changes to the implementation:
|
It seems important that locks not be taken away from code that believes it holds the lock without being explicitly released by the owner or by the entire db session being terminated and no longer accepting new sql commands (or commits). Maybe for an alternative to detecting a connection close it would be enough to notice an idle period when no request is active in the transaction? You'd be able to hold a lock indefinitely as long as you keep using it. If you stop using it for a few seconds then the session could be killed as a precaution. With the binary protocol, vtgate could explicitly kill the session sooner if the TCP connection dies. |
The lock is a system-wide guarantee. It's held by one vttablet (chosen as described above), and that vttablet cannot know activity in other vttablets where transactions are happening. However, the timeout for the lock is the same as the transaction. So, if the transaction doesn't complete within the timeout, it will be rolled back, and the lock will also be released due the same timeout. |
Issue #3631 get_lock and release_lock cannot be passed through to MySQL because their behavior is connection dependent, which doesn't work well for distributed systems, and for pooled connections. So, we implement our own version of these functions that are more distributed system friendly, with timeouts as well as session independent behaviors. More details on the issue.
Restricting named locks to master seems reasonable. Here are some of expectations that client code may have for the behavior of named locks within a client "session". I put "session" in quotes because that concept doesn't exist in vitess (none of these examples use transactions): Locks don't survive reparents:
Locks can't be released by the wrong person, or if they can they should kill the original session:
Disconnecting with the mysql binary protocol should release all named locks:
What happens if people try to hold a lock forever?... (maybe a client gets a lock with grpc and then crashes):
Satisfying these expectations seems to want some kind of vtgate awareness of a "session" which persists across transactions. |
Could you describe the use cases in more detail? We've already established that full mysql compatibility is not going to be practical. So, I think we're looking at a collaboration where vitess tries to meet the app half way, and some changes will have to be made in the app itself. |
Named locks are unsafe with server-side connection pooling. See vitessio#3631 for background. Signed-off-by: David Weitzman <dweitzman@pinterest.com>
Named locks acquired using the mysql get_lock() function are released explicitly by a call to release_lock() or implicitly when the session terminates. The release_lock() call must be from the very same mysql thread/session that called get_lock().
The problem: vtgate doesn't ensure that locks are freed when your vttablet session ends (naturally or abnormally). To make matters worse, committing a transaction will swap out the underlying mysql session so that calling release_lock() after a commit simple won't work.
The simple thing to do in the short term: disallow calls to get_lock() in vtgate for now for safety. That might look something like this:
Test case:
It seems like it should be possible to support named locks, though. A possible approach:
get_lock()
has been called and pin the current mysql session to the vitess session so they it can't be recycled after events like a commit or terminating the vttablet sessionRELEASE_ALL_LOCKS()
. Downside: requires mysql 5.7 or higherMy vote is that killing the underlying mysql connection is the right short-term choice. It's simple and it'll behave correctly across all mysql versions
The text was updated successfully, but these errors were encountered: