Skip to content

Commit 9812d85

Browse files
authored
*: activate txn for query on infoschema tables (#57937)
close #57874
1 parent d021648 commit 9812d85

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

pkg/executor/infoschema_reader.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,29 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex
115115

116116
// Cache the ret full rows in schemataRetriever
117117
if !e.initialized {
118-
is := sctx.GetInfoSchema().(infoschema.InfoSchema)
119-
e.is = is
120-
121118
var err error
119+
// InTxn() should be true in most of the cases.
120+
// Because the transaction should have been activated in MemTableReaderExec Open().
121+
// Why not just activate the txn here (sctx.Txn(true)) and do it in Open() instead?
122+
// Because it could DATA RACE here and in Open() it's safe.
123+
if sctx.GetSessionVars().InTxn() {
124+
e.is, err = domain.GetDomain(sctx).GetSnapshotInfoSchema(sctx.GetSessionVars().TxnCtx.StartTS)
125+
if err != nil {
126+
return nil, errors.Trace(err)
127+
}
128+
} else {
129+
// When the excutor is built from tidb coprocessor request, the transaction is not valid.
130+
// Then InTxn() is false.
131+
//
132+
// What's the difference between using latest infoschema and using snapshot infoschema?
133+
// A query *should* use the infoschema of the txn start ts, but it's still safe to use the latest.
134+
// If now it's 12:00:00, the ts of the latest infoschema might be 11:59:30 or 11:52:12 or anything.
135+
// Say, default GC interval is 10min, the ts of the latest infoschema is 11:52:12.
136+
// Then the valid lifetime range on infoschema API become [11:52:12, 12:12:12) using latest infoschema,
137+
// but it should be [12:00:00, 12:10:00) if using the snapshot infoschema.
138+
e.is = sctx.GetInfoSchema().(infoschema.InfoSchema)
139+
}
140+
122141
switch e.table.Name.O {
123142
case infoschema.TableSchemata:
124143
err = e.setDataFromSchemata(sctx)
@@ -177,7 +196,7 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex
177196
infoschema.TableClientErrorsSummaryByHost:
178197
err = e.setDataForClientErrorsSummary(sctx, e.table.Name.O)
179198
case infoschema.TableAttributes:
180-
err = e.setDataForAttributes(ctx, sctx, is)
199+
err = e.setDataForAttributes(ctx, sctx, e.is)
181200
case infoschema.TablePlacementPolicies:
182201
err = e.setDataFromPlacementPolicies(sctx)
183202
case infoschema.TableTrxSummary:

pkg/executor/memtable_reader.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ func (*MemTableReaderExec) isInspectionCacheableTable(tblName string) bool {
9393
}
9494
}
9595

96+
// Open implements the Executor Open interface.
97+
func (e *MemTableReaderExec) Open(ctx context.Context) error {
98+
err := e.BaseExecutor.Open(ctx)
99+
if err != nil {
100+
return errors.Trace(err)
101+
}
102+
103+
// Activate the transaction, otherwise SELECT .. FROM INFORMATION_SCHEMA.XX .. does not block GC worker.
104+
// And if the query last too long (10min), it causes error "GC life time is shorter than transaction duration"
105+
if txn, err1 := e.Ctx().Txn(false); err1 == nil && txn != nil && txn.Valid() {
106+
// Call e.Ctx().Txn(true) may panic, it's too difficult to debug all the callers.
107+
_, err = e.Ctx().Txn(true)
108+
}
109+
return err
110+
}
111+
96112
// Next implements the Executor Next interface.
97113
func (e *MemTableReaderExec) Next(ctx context.Context, req *chunk.Chunk) error {
98114
var (

0 commit comments

Comments
 (0)