diff --git a/config/config.go b/config/config.go index 1d97ce823e8ae..3e06f3d55ac70 100644 --- a/config/config.go +++ b/config/config.go @@ -225,6 +225,8 @@ type TiKVClient struct { GrpcKeepAliveTimeout uint `toml:"grpc-keepalive-timeout" json:"grpc-keepalive-timeout"` // CommitTimeout is the max time which command 'commit' will wait. CommitTimeout string `toml:"commit-timeout" json:"commit-timeout"` + // MaxTxnTimeUse is the max time a Txn may use (in seconds) from its startTS to commitTS. + MaxTxnTimeUse uint `toml:"max-txn-time-use" json:"max-txn-time-use"` } // Binlog is the config for binlog. @@ -306,6 +308,7 @@ var defaultConf = Config{ GrpcKeepAliveTime: 10, GrpcKeepAliveTimeout: 3, CommitTimeout: "41s", + MaxTxnTimeUse: 590, }, Binlog: Binlog{ WriteTimeout: "15s", diff --git a/config/config.toml.example b/config/config.toml.example index 727f0c22d43d4..313edf15d1c34 100644 --- a/config/config.toml.example +++ b/config/config.toml.example @@ -226,6 +226,11 @@ grpc-keepalive-timeout = 3 # max time for commit command, must be twice bigger than raft election timeout. commit-timeout = "41s" +# The max time a Txn may use (in seconds) from its startTS to commitTS. +# We use it to guarantee GC worker will not influence any active txn. Please make sure that this +# value is less than gc_life_time - 10s. +max-txn-time-use = 590 + [binlog] # Socket file to write binlog. diff --git a/store/tikv/2pc.go b/store/tikv/2pc.go index ec191ad77e79e..7fbd98041531a 100644 --- a/store/tikv/2pc.go +++ b/store/tikv/2pc.go @@ -23,6 +23,7 @@ import ( "github.com/juju/errors" "github.com/opentracing/opentracing-go" pb "github.com/pingcap/kvproto/pkg/kvrpcpb" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/sessionctx/binloginfo" @@ -80,6 +81,10 @@ type twoPhaseCommitter struct { syncLog bool connID uint64 // connID is used for log. cleanWg sync.WaitGroup + // The max time a Txn may use (in ms) from its startTS to commitTS. + // We use it to guarantee GC worker will not influence any active txn. The value + // should be less than GC life time. + maxTxnTimeUse uint64 } // newTwoPhaseCommitter creates a twoPhaseCommitter. @@ -144,18 +149,22 @@ func newTwoPhaseCommitter(txn *tikvTxn, connID uint64) (*twoPhaseCommitter, erro connID, tableID, size, len(keys), putCnt, delCnt, lockCnt, txn.startTS) } + // Convert from sec to ms + maxTxnTimeUse := uint64(config.GetGlobalConfig().TiKVClient.MaxTxnTimeUse) * 1000 + metrics.TiKVTxnWriteKVCountHistogram.Observe(float64(len(keys))) metrics.TiKVTxnWriteSizeHistogram.Observe(float64(size)) return &twoPhaseCommitter{ - store: txn.store, - txn: txn, - startTS: txn.StartTS(), - keys: keys, - mutations: mutations, - lockTTL: txnLockTTL(txn.startTime, size), - priority: getTxnPriority(txn), - syncLog: getTxnSyncLog(txn), - connID: connID, + store: txn.store, + txn: txn, + startTS: txn.StartTS(), + keys: keys, + mutations: mutations, + lockTTL: txnLockTTL(txn.startTime, size), + priority: getTxnPriority(txn), + syncLog: getTxnSyncLog(txn), + connID: connID, + maxTxnTimeUse: maxTxnTimeUse, }, nil } @@ -546,11 +555,6 @@ func (c *twoPhaseCommitter) cleanupKeys(bo *Backoffer, keys [][]byte) error { return c.doActionOnKeys(bo, actionCleanup, keys) } -// The max time a Txn may use (in ms) from its startTS to commitTS. -// We use it to guarantee GC worker will not influence any active txn. The value -// should be less than `gcRunInterval`. -const maxTxnTimeUse = 590000 - // execute executes the two-phase commit protocol. func (c *twoPhaseCommitter) execute(ctx context.Context) error { defer func() { @@ -619,7 +623,7 @@ func (c *twoPhaseCommitter) execute(ctx context.Context) error { return errors.Trace(err) } - if c.store.oracle.IsExpired(c.startTS, maxTxnTimeUse) { + if c.store.oracle.IsExpired(c.startTS, c.maxTxnTimeUse) { err = errors.Errorf("con:%d txn takes too much time, start: %d, commit: %d", c.connID, c.startTS, c.commitTS) return errors.Annotate(err, txnRetryableMark) }