docs/design/2022-03-03-rc-read-tso-optimization.md
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 unnecessary 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:
for_update_ts and just use the last valid one(start_ts for the first time).resultSet will be returned.Next function using the returned resultSet.chunk. The bottommost executor could be a pointGet, batchPointGet or a coprocessor task. What's different is a RcReadCheckTS flag will be set on all these read requests.WriteConflict error is reported.read_ts.ErrKeyIsLocked even though the lock.ts is greater than the read_ts as the read_ts could be a stale one.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.