Skip to content

Commit

Permalink
Merge branch 'master' into trace-row
Browse files Browse the repository at this point in the history
  • Loading branch information
tiancaiamao committed Jan 12, 2019
2 parents 59e0d0f + 504b10c commit d8e00a0
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 24 deletions.
7 changes: 7 additions & 0 deletions expression/builtin_encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ var aesModes = map[string]*aesModeAttr{
"aes-128-cbc": {"cbc", 16, true},
"aes-192-cbc": {"cbc", 24, true},
"aes-256-cbc": {"cbc", 32, true},
"aes-128-ofb": {"ofb", 16, true},
"aes-192-ofb": {"ofb", 24, true},
"aes-256-ofb": {"ofb", 32, true},
"aes-128-cfb": {"cfb", 16, true},
"aes-192-cfb": {"cfb", 24, true},
"aes-256-cfb": {"cfb", 32, true},
Expand Down Expand Up @@ -212,6 +215,8 @@ func (b *builtinAesDecryptIVSig) evalString(row chunk.Row) (string, bool, error)
switch b.modeName {
case "cbc":
plainText, err = encrypt.AESDecryptWithCBC([]byte(cryptStr), key, []byte(iv))
case "ofb":
plainText, err = encrypt.AESDecryptWithOFB([]byte(cryptStr), key, []byte(iv))
case "cfb":
plainText, err = encrypt.AESDecryptWithCFB([]byte(cryptStr), key, []byte(iv))
default:
Expand Down Expand Up @@ -337,6 +342,8 @@ func (b *builtinAesEncryptIVSig) evalString(row chunk.Row) (string, bool, error)
switch b.modeName {
case "cbc":
cipherText, err = encrypt.AESEncryptWithCBC([]byte(str), key, []byte(iv))
case "ofb":
cipherText, err = encrypt.AESEncryptWithOFB([]byte(str), key, []byte(iv))
case "cfb":
cipherText, err = encrypt.AESEncryptWithCFB([]byte(str), key, []byte(iv))
default:
Expand Down
7 changes: 7 additions & 0 deletions expression/builtin_encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ var aesTests = []struct {
{"aes-256-cbc", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "5D0E22C1E77523AEF5C3E10B65653C8F"},
{"aes-256-cbc", "pingcap", []interface{}{"12345678901234561234567890123456", "1234567890123456"}, "A26BA27CA4BE9D361D545AA84A17002D"},
{"aes-256-cbc", "pingcap", []interface{}{"1234567890123456", "12345678901234561234567890123456"}, "5D0E22C1E77523AEF5C3E10B65653C8F"},
// test for ofb
{"aes-128-ofb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "0515A36BBF3DE0"},
{"aes-128-ofb", "pingcap", []interface{}{"123456789012345678901234", "1234567890123456"}, "C2A93A93818546"},
{"aes-192-ofb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "FE09DCCF14D458"},
{"aes-256-ofb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "2E70FCAC0C0834"},
{"aes-256-ofb", "pingcap", []interface{}{"12345678901234561234567890123456", "1234567890123456"}, "83E2B30A71F011"},
{"aes-256-ofb", "pingcap", []interface{}{"1234567890123456", "12345678901234561234567890123456"}, "2E70FCAC0C0834"},
// test for cfb
{"aes-128-cfb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "0515A36BBF3DE0"},
{"aes-128-cfb", "pingcap", []interface{}{"123456789012345678901234", "1234567890123456"}, "C2A93A93818546"},
Expand Down
17 changes: 16 additions & 1 deletion expression/builtin_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ func (b *builtinJSONMergeSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNu
values = append(values, value)
}
res = json.MergeBinary(values)
// function "JSON_MERGE" is deprecated since MySQL 5.7.22. Synonym for function "JSON_MERGE_PRESERVE".
// See https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge
if b.pbCode == tipb.ScalarFuncSig_JsonMergeSig {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(errDeprecatedSyntaxNoReplacement.GenWithStackByArgs("JSON_MERGE"))
}
return res, false, nil
}

Expand Down Expand Up @@ -720,7 +725,17 @@ type jsonMergePreserveFunctionClass struct {
}

func (c *jsonMergePreserveFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_MERGE_PRESERVE")
if err := c.verifyArgs(args); err != nil {
return nil, err
}
argTps := make([]types.EvalType, 0, len(args))
for range args {
argTps = append(argTps, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
sig := &builtinJSONMergeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonMergePreserveSig)
return sig, nil
}

type jsonPrettyFunctionClass struct {
Expand Down
33 changes: 33 additions & 0 deletions expression/builtin_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,39 @@ func (s *testEvaluatorSuite) TestJSONMerge(c *C) {
j2 := d.GetMysqlJSON()
cmp := json.CompareBinary(j1, j2)
c.Assert(cmp, Equals, 0, Commentf("got %v expect %v", j1.String(), j2.String()))
case nil:
c.Assert(d.IsNull(), IsTrue)
}
}
}

func (s *testEvaluatorSuite) TestJSONMergePreserve(c *C) {
defer testleak.AfterTest(c)()
fc := funcs[ast.JSONMergePreserve]
tbl := []struct {
Input []interface{}
Expected interface{}
}{
{[]interface{}{nil, nil}, nil},
{[]interface{}{`{}`, `[]`}, `[{}]`},
{[]interface{}{`{}`, `[]`, `3`, `"4"`}, `[{}, 3, "4"]`},
}
for _, t := range tbl {
args := types.MakeDatums(t.Input...)
f, err := fc.getFunction(s.ctx, s.datumsToConstants(args))
c.Assert(err, IsNil)
d, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)

switch x := t.Expected.(type) {
case string:
j1, err := json.ParseBinaryFromString(x)
c.Assert(err, IsNil)
j2 := d.GetMysqlJSON()
cmp := json.CompareBinary(j1, j2)
c.Assert(cmp, Equals, 0, Commentf("got %v expect %v", j1.String(), j2.String()))
case nil:
c.Assert(d.IsNull(), IsTrue)
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,21 @@ func (s *testIntegrationSuite) TestEncryptionBuiltin(c *C) {
result.Check(testkit.Rows("341672829F84CB6B0BE690FEC4C4DAE9 341672829F84CB6B0BE690FEC4C4DAE9 D43734E147A12BB96C6897C4BBABA283 16F2C972411948DCEF3659B726D2CCB04AD1379A1A367FA64242058A50211B67 41E71D0C58967C1F50EEC074523946D1 1117D292E2D39C3EAA3B435371BE56FC 8ACB7ECC0883B672D7BD1CFAA9FA5FAF5B731ADE978244CD581F114D591C2E7E D2B13C30937E3251AEDA73859BA32E4B 2CF4A6051FF248A67598A17AA2C17267"))
result = tk.MustQuery("select HEX(AES_ENCRYPT('123', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT(123, 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('你好', 'foobar', '1234567890123456')), AES_ENCRYPT(NULL, 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`80D5646F07B4654B05A02D9085759770 80D5646F07B4654B05A02D9085759770 B3C14BA15030D2D7E99376DBE011E752 0CD2936EE4FEC7A8CDF6208438B2BC05 <nil>`))
tk.MustExec("SET block_encryption_mode='aes-128-ofb';")
result = tk.MustQuery("select HEX(AES_ENCRYPT(a, 'key', '1234567890123456')), HEX(AES_ENCRYPT(b, 'key', '1234567890123456')), HEX(AES_ENCRYPT(c, 'key', '1234567890123456')), HEX(AES_ENCRYPT(d, 'key', '1234567890123456')), HEX(AES_ENCRYPT(e, 'key', '1234567890123456')), HEX(AES_ENCRYPT(f, 'key', '1234567890123456')), HEX(AES_ENCRYPT(g, 'key', '1234567890123456')), HEX(AES_ENCRYPT(h, 'key', '1234567890123456')), HEX(AES_ENCRYPT(i, 'key', '1234567890123456')) from t")
result.Check(testkit.Rows("40 40 40C35C 40DD5EBDFCAA397102386E27DDF97A39ECCEC5 43DF55BAE0A0386D 78 47DC5D8AD19A085C32094E16EFC34A08D6FEF459 46D5 06840BE8"))
result = tk.MustQuery("select HEX(AES_ENCRYPT('123', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT(123, 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('你好', 'foobar', '1234567890123456')), AES_ENCRYPT(NULL, 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`48E38A 48E38A 9D6C199101C3 <nil>`))
tk.MustExec("SET block_encryption_mode='aes-192-ofb';")
result = tk.MustQuery("select HEX(AES_ENCRYPT(a, 'key', '1234567890123456')), HEX(AES_ENCRYPT(b, 'key', '1234567890123456')), HEX(AES_ENCRYPT(c, 'key', '1234567890123456')), HEX(AES_ENCRYPT(d, 'key', '1234567890123456')), HEX(AES_ENCRYPT(e, 'key', '1234567890123456')), HEX(AES_ENCRYPT(f, 'key', '1234567890123456')), HEX(AES_ENCRYPT(g, 'key', '1234567890123456')), HEX(AES_ENCRYPT(h, 'key', '1234567890123456')), HEX(AES_ENCRYPT(i, 'key', '1234567890123456')) from t")
result.Check(testkit.Rows("4B 4B 4B573F 4B493D42572E6477233A429BF3E0AD39DB816D 484B36454B24656B 73 4C483E757A1E555A130B62AAC1DA9D08E1B15C47 4D41 0D106817"))
result = tk.MustQuery("select HEX(AES_ENCRYPT('123', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT(123, 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('你好', 'foobar', '1234567890123456')), AES_ENCRYPT(NULL, 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`3A76B0 3A76B0 EFF92304268E <nil>`))
tk.MustExec("SET block_encryption_mode='aes-256-ofb';")
result = tk.MustQuery("select HEX(AES_ENCRYPT(a, 'key', '1234567890123456')), HEX(AES_ENCRYPT(b, 'key', '1234567890123456')), HEX(AES_ENCRYPT(c, 'key', '1234567890123456')), HEX(AES_ENCRYPT(d, 'key', '1234567890123456')), HEX(AES_ENCRYPT(e, 'key', '1234567890123456')), HEX(AES_ENCRYPT(f, 'key', '1234567890123456')), HEX(AES_ENCRYPT(g, 'key', '1234567890123456')), HEX(AES_ENCRYPT(h, 'key', '1234567890123456')), HEX(AES_ENCRYPT(i, 'key', '1234567890123456')) from t")
result.Check(testkit.Rows("16 16 16D103 16CF01CBC95D33E2ED721CBD930262415A69AD 15CD0ACCD55732FE 2E 11CE02FCE46D02CFDD433C8CA138527060599C35 10C7 5096549E"))
result = tk.MustQuery("select HEX(AES_ENCRYPT('123', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT(123, 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('你好', 'foobar', '1234567890123456')), AES_ENCRYPT(NULL, 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`E842C5 E842C5 3DCD5646767D <nil>`))

// for AES_DECRYPT
tk.MustExec("SET block_encryption_mode='aes-128-ecb';")
Expand All @@ -1018,6 +1033,21 @@ func (s *testIntegrationSuite) TestEncryptionBuiltin(c *C) {
result.Check(testkit.Rows("foo"))
result = tk.MustQuery("select AES_DECRYPT(UNHEX('80D5646F07B4654B05A02D9085759770'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('B3C14BA15030D2D7E99376DBE011E752'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('0CD2936EE4FEC7A8CDF6208438B2BC05'), 'foobar', '1234567890123456'), AES_DECRYPT(NULL, 'foobar', '1234567890123456'), AES_DECRYPT('SOME_THING_STRANGE', 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`123 你好 <nil> <nil>`))
tk.MustExec("SET block_encryption_mode='aes-128-ofb';")
result = tk.MustQuery("select AES_DECRYPT(AES_ENCRYPT('foo', 'bar', '1234567890123456'), 'bar', '1234567890123456')")
result.Check(testkit.Rows("foo"))
result = tk.MustQuery("select AES_DECRYPT(UNHEX('48E38A'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX(''), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('9D6C199101C3'), 'foobar', '1234567890123456'), AES_DECRYPT(NULL, 'foobar', '1234567890123456'), HEX(AES_DECRYPT('SOME_THING_STRANGE', 'foobar', '1234567890123456'))")
result.Check(testkit.Rows(`123 你好 <nil> 2A9EF431FB2ACB022D7F2E7C71EEC48C7D2B`))
tk.MustExec("SET block_encryption_mode='aes-192-ofb';")
result = tk.MustQuery("select AES_DECRYPT(AES_ENCRYPT('foo', 'bar', '1234567890123456'), 'bar', '1234567890123456')")
result.Check(testkit.Rows("foo"))
result = tk.MustQuery("select AES_DECRYPT(UNHEX('3A76B0'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX(''), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('EFF92304268E'), 'foobar', '1234567890123456'), AES_DECRYPT(NULL, 'foobar', '1234567890123456'), HEX(AES_DECRYPT('SOME_THING_STRANGE', 'foobar', '1234567890123456'))")
result.Check(testkit.Rows(`123 你好 <nil> 580BCEA4DC67CF33FF2C7C570D36ECC89437`))
tk.MustExec("SET block_encryption_mode='aes-256-ofb';")
result = tk.MustQuery("select AES_DECRYPT(AES_ENCRYPT('foo', 'bar', '1234567890123456'), 'bar', '1234567890123456')")
result.Check(testkit.Rows("foo"))
result = tk.MustQuery("select AES_DECRYPT(UNHEX('E842C5'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX(''), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('3DCD5646767D'), 'foobar', '1234567890123456'), AES_DECRYPT(NULL, 'foobar', '1234567890123456'), HEX(AES_DECRYPT('SOME_THING_STRANGE', 'foobar', '1234567890123456'))")
result.Check(testkit.Rows(`123 你好 <nil> 8A3FBBE68C9465834584430E3AEEBB04B1F5`))

// for COMPRESS
tk.MustExec("DROP TABLE IF EXISTS t1;")
Expand Down
9 changes: 1 addition & 8 deletions server/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ func (cc *clientConn) openSessionAndDoAuth(authData []byte) error {
// This function returns and the connection is closed if there is an IO error or there is a panic.
func (cc *clientConn) Run() {
const size = 4096
closedOutside := false
defer func() {
r := recover()
if r != nil {
Expand All @@ -535,7 +534,7 @@ func (cc *clientConn) Run() {
log.Errorf("lastCmd %s, %v, %s", cc.lastCmd, r, buf)
metrics.PanicCounter.WithLabelValues(metrics.LabelSession).Inc()
}
if !closedOutside {
if atomic.LoadInt32(&cc.status) != connStatusShutdown {
err := cc.Close()
terror.Log(errors.Trace(err))
}
Expand All @@ -548,9 +547,6 @@ func (cc *clientConn) Run() {
// by CAS operation, it would then take some actions accordingly.
for {
if atomic.CompareAndSwapInt32(&cc.status, connStatusDispatching, connStatusReading) == false {
if atomic.LoadInt32(&cc.status) == connStatusShutdown {
closedOutside = true
}
return
}

Expand All @@ -577,9 +573,6 @@ func (cc *clientConn) Run() {
}

if atomic.CompareAndSwapInt32(&cc.status, connStatusReading, connStatusDispatching) == false {
if atomic.LoadInt32(&cc.status) == connStatusShutdown {
closedOutside = true
}
return
}

Expand Down
32 changes: 30 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
package server

import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
Expand Down Expand Up @@ -436,22 +437,49 @@ func (s *Server) KillAllConnections() {
}
}

var gracefulCloseConnectionsTimeout = 15 * time.Second

// TryGracefulDown will try to gracefully close all connection first with timeout. if timeout, will close all connection directly.
func (s *Server) TryGracefulDown() {
ctx, cancel := context.WithTimeout(context.Background(), gracefulCloseConnectionsTimeout)
defer cancel()
done := make(chan struct{})
go func() {
s.GracefulDown(ctx, done)
}()
select {
case <-ctx.Done():
s.KillAllConnections()
case <-done:
return
}
}

// GracefulDown waits all clients to close.
func (s *Server) GracefulDown() {
func (s *Server) GracefulDown(ctx context.Context, done chan struct{}) {
log.Info("[server] graceful shutdown.")
metrics.ServerEventCounter.WithLabelValues(metrics.EventGracefulDown).Inc()

count := s.ConnectionCount()
for i := 0; count > 0; i++ {
time.Sleep(time.Second)
s.kickIdleConnection()

count = s.ConnectionCount()
if count == 0 {
break
}
// Print information for every 30s.
if i%30 == 0 {
log.Infof("graceful shutdown...connection count %d\n", count)
}
ticker := time.After(time.Second)
select {
case <-ctx.Done():
return
case <-ticker:
}
}
close(done)
}

func (s *Server) kickIdleConnection() {
Expand Down
33 changes: 26 additions & 7 deletions session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,23 +514,42 @@ func (s *session) isRetryableError(err error) bool {
return kv.IsRetryableError(err) || domain.ErrInfoSchemaChanged.Equal(err)
}

func (s *session) retry(ctx context.Context, maxCnt uint) error {
connID := s.sessionVars.ConnectionID
if s.sessionVars.TxnCtx.ForUpdate {
return errForUpdateCantRetry.GenWithStackByArgs(connID)
func (s *session) checkTxnAborted(stmt sqlexec.Statement) error {
if s.txn.doNotCommit == nil {
return nil
}
s.sessionVars.RetryInfo.Retrying = true
// If the transaction is aborted, the following statements do not need to execute, except `commit` and `rollback`,
// because they are used to finish the aborted transaction.
if _, ok := stmt.(*executor.ExecStmt).StmtNode.(*ast.CommitStmt); ok {
return nil
}
if _, ok := stmt.(*executor.ExecStmt).StmtNode.(*ast.RollbackStmt); ok {
return nil
}
return errors.New("current transaction is aborted, commands ignored until end of transaction block")
}

func (s *session) retry(ctx context.Context, maxCnt uint) (err error) {
var retryCnt uint
defer func() {
s.sessionVars.RetryInfo.Retrying = false
s.txn.changeToInvalid()
// retryCnt only increments on retryable error, so +1 here.
metrics.SessionRetry.Observe(float64(retryCnt + 1))
s.sessionVars.SetStatusFlag(mysql.ServerStatusInTrans, false)
if err != nil {
s.rollbackOnError(ctx)
}
s.txn.changeToInvalid()
}()

connID := s.sessionVars.ConnectionID
s.sessionVars.RetryInfo.Retrying = true
if s.sessionVars.TxnCtx.ForUpdate {
err = errForUpdateCantRetry.GenWithStackByArgs(connID)
return err
}

nh := GetHistory(s)
var err error
var schemaVersion int64
sessVars := s.GetSessionVars()
orgStartTS := sessVars.TxnCtx.StartTS
Expand Down
41 changes: 38 additions & 3 deletions session/session_fail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,48 @@ func (s *testSessionSuite) TestFailStatementCommit(c *C) {

gofail.Disable("github.com/pingcap/tidb/session/mockStmtCommitError")

tk.MustQuery("select * from t").Check(testkit.Rows("1"))
tk.MustExec("insert into t values (3)")
tk.MustExec("insert into t values (4)")
_, err = tk.Exec("select * from t")
c.Assert(err, NotNil)
_, err = tk.Exec("insert into t values (3)")
c.Assert(err, NotNil)
_, err = tk.Exec("insert into t values (4)")
c.Assert(err, NotNil)
_, err = tk.Exec("commit")
c.Assert(err, NotNil)

tk.MustQuery(`select * from t`).Check(testkit.Rows())

tk.MustExec("insert into t values (1)")

tk.MustExec("begin")
tk.MustExec("insert into t values (2)")
tk.MustExec("commit")

tk.MustExec("begin")
tk.MustExec("insert into t values (3)")
tk.MustExec("rollback")

tk.MustQuery(`select * from t`).Check(testkit.Rows("1", "2"))
}

func (s *testSessionSuite) TestFailStatementCommitInRetry(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (id int)")

tk.MustExec("begin")
tk.MustExec("insert into t values (1)")
tk.MustExec("insert into t values (2),(3),(4),(5)")
tk.MustExec("insert into t values (6)")

gofail.Enable("github.com/pingcap/tidb/session/mockCommitError8942", `return(true)`)
gofail.Enable("github.com/pingcap/tidb/session/mockStmtCommitError", `return(true)`)
_, err := tk.Exec("commit")
c.Assert(err, NotNil)
gofail.Disable("github.com/pingcap/tidb/session/mockCommitError8942")
gofail.Disable("github.com/pingcap/tidb/session/mockStmtCommitError")

tk.MustExec("insert into t values (6)")
tk.MustQuery(`select * from t`).Check(testkit.Rows("6"))
}

func (s *testSessionSuite) TestGetTSFailDirtyState(c *C) {
Expand Down
4 changes: 4 additions & 0 deletions session/tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ func runStmt(ctx context.Context, sctx sessionctx.Context, s sqlexec.Statement)
var err error
var rs sqlexec.RecordSet
se := sctx.(*session)
err = se.checkTxnAborted(s)
if err != nil {
return nil, err
}
rs, err = s.Exec(ctx)
sessVars := se.GetSessionVars()
// All the history should be added here.
Expand Down
7 changes: 7 additions & 0 deletions session/txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ func (st *TxnState) Commit(ctx context.Context) error {
}
return errors.Trace(st.doNotCommit)
}

// mockCommitError8942 is used for PR #8942.
// gofail: var mockCommitError8942 bool
// if mockCommitError8942 {
// return kv.ErrRetryable
// }

return errors.Trace(st.Transaction.Commit(ctx))
}

Expand Down
Loading

0 comments on commit d8e00a0

Please sign in to comment.