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会失败。