From d4d4bac1dc280ebefc51a7b9180269813466ae4e Mon Sep 17 00:00:00 2001 From: Lynn Date: Tue, 17 Apr 2018 18:44:06 +0800 Subject: [PATCH] ddl: support the rolling upgrade. (#6301) --- ddl/column.go | 7 +++++++ ddl/ddl_api.go | 11 ++++++++++- ddl/fail_db_test.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 ddl/fail_db_test.go diff --git a/ddl/column.go b/ddl/column.go index 100ce7af3de7a..b02177f0d8bed 100644 --- a/ddl/column.go +++ b/ddl/column.go @@ -460,6 +460,13 @@ func (d *ddl) doModifyColumn(t *meta.Meta, job *model.Job, newCol *model.ColumnI } } + // gofail: var uninitializedOffsetAndState bool + // if uninitializedOffsetAndState { + // if newCol.State != model.StatePublic { + // return ver, errors.New("the column state is wrong") + // } + // } + // We need the latest column's offset and state. This information can be obtained from the store. newCol.Offset = oldCol.Offset newCol.State = oldCol.State diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 4455603772c02..8836a23f451fe 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -1372,7 +1372,16 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or } newCol := table.ToColumn(&model.ColumnInfo{ - ID: col.ID, + ID: col.ID, + // We use this PR(https://github.com/pingcap/tidb/pull/6274) as the dividing line to define whether it is a new version or an old version TiDB. + // The old version TiDB initializes the column's offset and state here. + // The new version TiDB doesn't initialize the column's offset and state, and it will do the initialization in run DDL function. + // When we do the rolling upgrade the following may happen: + // a new version TiDB builds the DDL job that doesn't be set the column's offset and state, + // and the old version TiDB is the DDL owner, it doesn't get offset and state from the store. Then it will encounter errors. + // So here we set offset and state to support the rolling upgrade. + Offset: col.Offset, + State: col.State, OriginDefaultValue: col.OriginDefaultValue, FieldType: *specNewColumn.Tp, Name: newColName, diff --git a/ddl/fail_db_test.go b/ddl/fail_db_test.go new file mode 100644 index 0000000000000..bc6a9d7e03eba --- /dev/null +++ b/ddl/fail_db_test.go @@ -0,0 +1,35 @@ +// Copyright 2018 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + gofail "github.com/coreos/gofail/runtime" + . "github.com/pingcap/check" + "golang.org/x/net/context" +) + +// TestInitializeOffsetAndState tests the case that the column's offset and state don't be initialized in the file of ddl_api.go when +// doing the operation of 'modify column'. +func (s *testStateChangeSuite) TestInitializeOffsetAndState(c *C) { + _, err := s.se.Execute(context.Background(), "use test_db_state") + c.Assert(err, IsNil) + _, err = s.se.Execute(context.Background(), "create table t(a int, b int, c int)") + c.Assert(err, IsNil) + defer s.se.Execute(context.Background(), "drop table t") + + gofail.Enable("github.com/pingcap/tidb/ddl/uninitializedOffsetAndState", `return(true)`) + _, err = s.se.Execute(context.Background(), "ALTER TABLE t MODIFY COLUMN b int FIRST;") + c.Assert(err, IsNil) + gofail.Disable("github.com/pingcap/tidb/ddl/uninitializedOffsetAndState") +}