Skip to content

Commit

Permalink
session: fix auto commit variable change effect on transaction commit (
Browse files Browse the repository at this point in the history
  • Loading branch information
cfzjywxk committed Aug 1, 2022
1 parent cb211e0 commit 1cd8c31
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 11 deletions.
1 change: 1 addition & 0 deletions executor/executor_txn_test.go
Expand Up @@ -297,6 +297,7 @@ func TestTxnSavepoint0(t *testing.T) {
{"set autocommit=1", nil, ""},
{"savepoint s1", nil, ""},

{"set autocommit=0", nil, ""},
{"begin", nil, ""},
{"savepoint s1", []string{"s1"}, ""},
{"set autocommit=1", nil, ""},
Expand Down
52 changes: 43 additions & 9 deletions session/session_test/session_test.go
Expand Up @@ -3646,7 +3646,7 @@ func TestAutocommit(t *testing.T) {

// When autocommit is 0, transaction start ts should be the first *valid*
// statement, rather than *any* statement.
tk.MustExec("create table t (id int)")
tk.MustExec("create table t (id int key)")
tk.MustExec("set @@autocommit = 0")
tk.MustExec("rollback")
tk.MustExec("set @@autocommit = 0")
Expand All @@ -3656,15 +3656,49 @@ func TestAutocommit(t *testing.T) {
tk1.MustExec("insert into t select 1")

tk.MustQuery("select * from t").Check(testkit.Rows("1"))
tk.MustExec("delete from t")

// When the transaction is rolled back, the global set statement would succeed.
tk.MustExec("set @@global.autocommit = 0")
tk.MustExec("begin")
tk.MustExec("insert into t values (1)")
tk.MustExec("set @@global.autocommit = 1")
tk.MustExec("rollback")
tk.MustQuery("select count(*) from t where id = 1").Check(testkit.Rows("0"))
tk.MustQuery("select @@global.autocommit").Check(testkit.Rows("1"))

// TODO: MySQL compatibility for setting global variable.
// tk.MustExec("begin")
// tk.MustExec("insert into t values (42)")
// tk.MustExec("set @@global.autocommit = 1")
// tk.MustExec("rollback")
// tk.MustQuery("select count(*) from t where id = 42").Check(testkit.Rows("0"))
// Even the transaction is rollbacked, the set statement succeed.
// tk.MustQuery("select @@global.autocommit").Rows("1")
// When the transaction is committed because of switching mode, the session set statement shold succeed.
tk.MustExec("set autocommit = 0")
tk.MustExec("begin")
tk.MustExec("insert into t values (1)")
tk.MustExec("set autocommit = 1")
tk.MustExec("rollback")
tk.MustQuery("select count(*) from t where id = 1").Check(testkit.Rows("1"))
tk.MustQuery("select @@autocommit").Check(testkit.Rows("1"))

tk.MustExec("set autocommit = 0")
tk.MustExec("insert into t values (2)")
tk.MustExec("set autocommit = 1")
tk.MustExec("rollback")
tk.MustQuery("select count(*) from t where id = 2").Check(testkit.Rows("1"))
tk.MustQuery("select @@autocommit").Check(testkit.Rows("1"))

// Set should not take effect if the mode is not changed.
tk.MustExec("set autocommit = 0")
tk.MustExec("begin")
tk.MustExec("insert into t values (3)")
tk.MustExec("set autocommit = 0")
tk.MustExec("rollback")
tk.MustQuery("select count(*) from t where id = 3").Check(testkit.Rows("0"))
tk.MustQuery("select @@autocommit").Check(testkit.Rows("0"))

tk.MustExec("set autocommit = 1")
tk.MustExec("begin")
tk.MustExec("insert into t values (4)")
tk.MustExec("set autocommit = 1")
tk.MustExec("rollback")
tk.MustQuery("select count(*) from t where id = 4").Check(testkit.Rows("0"))
tk.MustQuery("select @@autocommit").Check(testkit.Rows("1"))
}

// TestTxnLazyInitialize tests that when autocommit = 0, not all statement starts
Expand Down
5 changes: 3 additions & 2 deletions sessionctx/variable/sysvar.go
Expand Up @@ -953,10 +953,11 @@ var defaultSysVars = []*SysVar{
}},
{Scope: ScopeGlobal | ScopeSession, Name: AutoCommit, Value: On, Type: TypeBool, SetSession: func(s *SessionVars, val string) error {
isAutocommit := TiDBOptOn(val)
s.SetStatusFlag(mysql.ServerStatusAutocommit, isAutocommit)
if isAutocommit {
// Implicitly commit the possible ongoing transaction if mode is changed from off to on.
if !s.IsAutocommit() && isAutocommit {
s.SetInTxn(false)
}
s.SetStatusFlag(mysql.ServerStatusAutocommit, isAutocommit)
return nil
}},
{Scope: ScopeGlobal | ScopeSession, Name: CharsetDatabase, Value: mysql.DefaultCharset, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) {
Expand Down

0 comments on commit 1cd8c31

Please sign in to comment.