func (cc *clientConn) Run() { defer func() { r := recover() if r != nil { const size = 4096 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] log.Errorf("lastCmd %s, %v, %s", cc.lastCmd, r, buf) } cc.Close() }() for { cc.alloc.Reset() data, err := cc.readPacket() if err != nil { if errors2.ErrorNotEqual(err, io.EOF) { log.Error(err) } return } if err := cc.dispatch(data); err != nil { if errors2.ErrorEqual(err, io.EOF) { return } log.Errorf("dispatch error %s, %s", errors.ErrorStack(err), cc) log.Errorf("cmd: %s", string(data[1:])) cc.writeError(err) } cc.pkg.sequence = 0 } }
// See: http://dev.mysql.com/doc/refman/5.7/en/commit.html func (s *testSessionSuite) TestRowLock(c *C) { store := newStore(c, s.dbName) se := newSession(c, store, s.dbName) se1 := newSession(c, store, s.dbName) se2 := newSession(c, store, s.dbName) mustExecSQL(c, se, "drop table if exists t") c.Assert(se.(*session).txn, IsNil) mustExecSQL(c, se, "create table t (c1 int, c2 int, c3 int)") mustExecSQL(c, se, "insert t values (11, 2, 3)") mustExecSQL(c, se, "insert t values (12, 2, 3)") mustExecSQL(c, se, "insert t values (13, 2, 3)") mustExecSQL(c, se1, "begin") mustExecSQL(c, se1, "update t set c2=21 where c1=11") mustExecSQL(c, se2, "begin") mustExecSQL(c, se2, "update t set c2=211 where c1=11") mustExecSQL(c, se2, "commit") _, err := exec(c, se1, "commit") // row lock conflict but can still success if errors2.ErrorNotEqual(err, kv.ErrConditionNotMatch) { c.Fail() } // Retry should success err = se.Retry() c.Assert(err, IsNil) mustExecSQL(c, se1, "begin") mustExecSQL(c, se1, "update t set c2=21 where c1=11") mustExecSQL(c, se2, "begin") mustExecSQL(c, se2, "update t set c2=22 where c1=12") mustExecSQL(c, se2, "commit") mustExecSQL(c, se1, "commit") mustExecSQL(c, se, s.dropDBSQL) }