ddl: check constraint name. #72
修复了问题#66。
出现原因:
tbInfo, err := d.buildTableInfo(ident.Name, cols, newConstraints) if err != nil { return errors.Trace(err) }
https://github.com/pingcap/tidb/blob/1e4cdb813feab70b19487e1793eb51b87bc3bf7c/ddl/ddl.go#L324-L327
这里的newConstraints的ConstrName全部是””
导致kvIndex的KEY前缀都是相同的:
err = d.updateInfoSchema(ctx, ident.Schema, tbInfo) return errors.Trace(err) }
https://github.com/pingcap/tidb/blob/a54c896dcfde55ae97ffd5e0c14c895f13645f37/ddl/ddl.go#L367-L369
d.infoHandle.Set(clonedInfo) return nil }
https://github.com/pingcap/tidb/blob/a54c896dcfde55ae97ffd5e0c14c895f13645f37/ddl/ddl.go#L664-L666
info.tables[t.ID] = table.TableFromMeta(di.Name.L, alloc, t) tname := tableName{di.Name.L, t.Name.L}
func TableFromMeta(dbname string, alloc autoid.Allocator, tblInfo *model.TableInfo) table.Table { t := NewTable(tblInfo.ID, tblInfo.Name.O, dbname, nil, alloc) for _, colInfo := range tblInfo.Columns { c := column.Col{ColumnInfo: *colInfo} t.Columns = append(t.Columns, &c) } for _, idxInfo := range tblInfo.Indices { idx := &column.IndexedCol{ IndexInfo: *idxInfo, X: kv.NewKVIndex(t.indexPrefix, idxInfo.Name.L, idxInfo.Unique), } t.AddIndex(idx) } return t }
// NewKVIndex builds a new kvIndex object. func NewKVIndex(indexPrefix, indexName string, unique bool) Index { return &kvIndex{ indexName: indexName, unique: unique, prefix: genIndexPrefix(indexPrefix, indexName), } }
那么所有索引的prefix全部相同的话,每行数据都会插入对应的索引,在按照索引查询时就会出现索引个数个重复的行。
所以这里在创建索引前把indexName填上且不重复即可。
Parser: Adjust the syntax error log #65
调整了错误日志格式。
fix driver panic #78
为了解决issue https://github.com/pingcap/tidb/issues/57
这里还未完全解决,只是在newdriverRows中goroutine加了sync.WaitGroup
parser: resolve reduce/reduce conflicts #86
issue #73 ,解决了部分解析器上的冲突(这里还未最终解决)。
关于Lex和Yacc的内容,看这里有一系列详解http://blog.csdn.net/liwei_cmg/article/details/1530492
然后这里是用了golang版本的goyacc。
Retry transaction without for update #79
对修改操作支持冲突事务重新提交。
跟着这个test看一下:
// 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, Equals, nil) 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) }
在提交这个commit会失败,_, err := exec(c, se1, “commit”)。
这个PR就是让这个失败后重新提交。
if !bytes.Equal(currValue, snapshotVal) { log.Warnf("txn:%d, tryLockKey condition not match for key %s, currValue:%s, snapshotVal:%s", tID, key, currValue, snapshotVal) return errors.Trace(kv.ErrConditionNotMatch) } s.keysLocked[key] = tID return nil }
在这里发现数据已经被修改过了,然后commit会失败。