You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We refactored the implementation of stale read in #32699 and #33812. Recapping these PRs, we did below things:
Added two methods GetReadTS and GetForUpdateTS to TxnManager and put some information like stale read timestamp to the StalenessTxnProvider. This makes the transaction information easier to obtain and also fixes some problems caused by passing those information by parameters: Got error when stale read with scalar subquery #31954
After #33812 merged, we will continue to refactor the RC isolation part. We'll also provide a txn provider for RC to manage its own context. Different with stale read, RC is a little complex, for example:
RC will do the current read instead of snapshot read for every statement. So if we do not do any optimization, the read ts for each statement is not the same.
RC supports write and for update operations. If the forUpdateTS is out of date, an ErrWriteConflict will return from storage layer and the statement should update forUpdateTS and then retry.
Since RC often uses different ts for each statement. The TxnManager needs to separate different statements. So we added some methods to tell TxnManager this information:
type TxnManager interface {
// EnterNewTxn enters a new txn
EnterNewTxn(ctx context.Context, request *NewTxnRequest) error
// OnStmtStart is the hook that should be called when a new statement started
OnStmtStart(ctx context.Context) error
// OnStmtError is the hook that should be called when statement get an error
OnStmtError(err error)
// OnStmtRetry is the hook that should be called when a statement is retrying
OnStmtRetry(ctx context.Context) error
// other methods
...
}
EnterNewTxn makes TxnManager enter to a new transaction. This method will set a new provider for the next transaction according to the environment and the parameter NewTxnRequest. Currently two places are using this method:
Every time a new statement is started and this statement is not in an explicit transaction:
OnStmtStart will be called every time when entering a new statement. For the RC scenario, this method will tell RC's provider to update its read timestamp.
OnStmtRetry will be called when retrying the statement. The retry often happens forUpdateTS is out of date and the provider should update it.
OnStmtError will be called when get an error while executing the statement. If one statement retried multiple times and failed at last, OnStmtError will only be called once.
Below is the examples to illustrate the order in which these methods are called:
If the RC check optimization failed and the storage layer returns an error. It will be regarded as a statement failure and then re-execute the SQL again. The OnStmtRetry is not called and the OnStmtStart will be called twice. The reason for simple.
In the above implementation readcomitted.txnContextProvider maintains the statement's TSO future internally to decouple these states from the session. And then we move the most logic of RC to the provider and the method executorBuilder.getReadTS is simplified.
We also moved the logic of the Txn initialization to the provider and provided the method ActiveTxn for external calls. At this point the logic in SimpleExec.executeBegin is also greatly simplified.
Use Advise to do some optimizations
When doing refactor we needs to keep the exist optimizations work. For some optimizations such as RCCheck, we have enough information in provider so it's easy to do it. But for other optimizations we do not have insufficient informations in provider to support it.
So we introduce a new method Advise to give provider some extra informations. Different with other methods, it:
It is optional. That it, whether users use Advise or not, the correctness of the provider should not be affected.
If user give a Advice with a "right" information, the behavior of the provider should be correct too. The "right" should be easy for users to achieve. For example some optimization will require an extra logical plan information, the user should guarantee the plan is "right" in the advice. The provider should keep it correctness when the user advises it in a wrong time but it is allowed that optimization will not take affect when it happens.
We now use WarmUp advice to prepare parallel tso future, see:
We refactored the implementation of stale read in #32699 and #33812. Recapping these PRs, we did below things:
GetReadTS
andGetForUpdateTS
toTxnManager
and put some information like stale read timestamp to theStalenessTxnProvider
. This makes the transaction information easier to obtain and also fixes some problems caused by passing those information by parameters: Got error when stale read with scalar subquery #31954After #33812 merged, we will continue to refactor the RC isolation part. We'll also provide a txn provider for RC to manage its own context. Different with stale read, RC is a little complex, for example:
ErrWriteConflict
will return from storage layer and the statement should update forUpdateTS and then retry.Some the descriptions above is also be applied to RR isolation or optimistic transactions. Next we will do some refactors according to them.
The design
The draft code is here: #33995
Add some lifecycle hook methods to
TxnManager
Since RC often uses different ts for each statement. The
TxnManager
needs to separate different statements. So we added some methods to tellTxnManager
this information:EnterNewTxn
makes TxnManager enter to a new transaction. This method will set a new provider for the next transaction according to the environment and the parameterNewTxnRequest
. Currently two places are using this method:tidb/session/session.go
Lines 3133 to 3135 in e631e65
start transaction
orbegin
:tidb/executor/simple.go
Lines 603 to 608 in e631e65
OnStmtStart
will be called every time when entering a new statement. For the RC scenario, this method will tell RC's provider to update its read timestamp.OnStmtRetry
will be called when retrying the statement. The retry often happens forUpdateTS is out of date and the provider should update it.OnStmtError
will be called when get an error while executing the statement. If one statement retried multiple times and failed at last,OnStmtError
will only be called once.Below is the examples to illustrate the order in which these methods are called:
If the RC check optimization failed and the storage layer returns an error. It will be regarded as a statement failure and then re-execute the SQL again. The
OnStmtRetry
is not called and theOnStmtStart
will be called twice. The reason for simple.Move RC's states to provider
We introduced a new class
readcomitted.txnContextProvider
to provide RC context. See the code here: https://github.com/pingcap/tidb/pull/33995/files#diff-4aa25ab176e21d35039cf22c45777a51bd4a0a5c18eecde002750dfe76663602R137In the above implementation
readcomitted.txnContextProvider
maintains the statement's TSO future internally to decouple these states from the session. And then we move the most logic of RC to the provider and the methodexecutorBuilder.getReadTS
is simplified.We also moved the logic of the Txn initialization to the provider and provided the method
ActiveTxn
for external calls. At this point the logic inSimpleExec.executeBegin
is also greatly simplified.Use
Advise
to do some optimizationsWhen doing refactor we needs to keep the exist optimizations work. For some optimizations such as RCCheck, we have enough information in provider so it's easy to do it. But for other optimizations we do not have insufficient informations in provider to support it.
So we introduce a new method
Advise
to give provider some extra informations. Different with other methods, it:Advise
or not, the correctness of the provider should not be affected.Advice
with a "right" information, the behavior of the provider should be correct too. The "right" should be easy for users to achieve. For example some optimization will require an extra logical plan information, the user should guarantee the plan is "right" in the advice. The provider should keep it correctness when the user advises it in a wrong time but it is allowed that optimization will not take affect when it happens.We now use
WarmUp
advice to prepare parallel tso future, see:tidb/planner/optimize.go
Line 147 in 5193dc0
The text was updated successfully, but these errors were encountered: