- Author(s): cfzjywxk
- Last updated: March. 3, 2022
- Discussion at:
For the read-committed
isolation level, each read request in a single transaction will need to fetch a new ts
to read the latest committed data.
If the workload is a read-heavy one whose read QPS is significantly higher than writes or there're few read-write conflicts, fetching ts each time will increase the query lantecy.
The new ts itself is used to ensure the most recent data will be returned, if the data version does not change frequently then it's unnecessary to fetch a new timestamp every time. The ts fetching could be processed in an optimistic way that ts fetching happens only when a more recent data version is encoutered, this saves the cost of many unncessary ts fetching.
Introduce another system variable tidb_rc_read_check_ts
to enable the "lazy ts fetch" read mode. It will take effect for all the in-transaction select statements when the transaction mode is pessimistic
and the isolation level is read-committed
.
The execution flow is like this:
- If the query is executed first time, do not fetch a new
for_update_ts
and just use the last valid one(start_ts
for the first time). - Do build the plan and executor like before.
- If the execution is successful, a
resultSet
will be returned. - The connection layer will drive the response procesure and call
Next
function using the returnedresultSet
. - The read executor will try to fetch data to fill in a data
chunk
. The bottommost executor could be apointGet
,batchPointGet
or a coprocessor task. What's different is aRcReadCheckTS
flag will be set on all these read requests. - The read executor in the storage layer will check the read results, if a more recent version does exist then a
WriteConflict
error is reported. - For data write record, do check if it's newer than the current
read_ts
. - For lock record, return
ErrKeyIsLocked
even though thelock.ts
is greater than theread_ts
as theread_ts
could be a stale one. - If no error is returned then the query is finished. Otherwise if there's no
chunk
responsed to the client yet, retry the whole query fetching a new global ts to do the read like normal.
The default behaviours of the read-committed
isolation level will not change. One thing different is that if the user client uses COM_STMT_FETCH
like utility to read data from TiDB
,
there could be problem if the returned first chunk result is already used by the client but an error is reported processing next result chunk.