Skip to content

Commit

Permalink
Merge pull request #8517 from planetscale/onlineddl-stale-migration-c…
Browse files Browse the repository at this point in the history
…ompeleted-timestamp-release-11

Backport: Fixing multiple issues related to onlineddl/lifecycle
  • Loading branch information
deepthi authored Jul 23, 2021
2 parents 94d3d54 + 0d56514 commit b0a094d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 21 deletions.
14 changes: 14 additions & 0 deletions go/vt/schema/tablegc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestIsGCTableName(t *testing.T) {
Expand Down Expand Up @@ -152,3 +153,16 @@ func TestParseGCLifecycle(t *testing.T) {
})
}
}

func TestGenerateRenameStatementWithUUID(t *testing.T) {
uuid := "997342e3_e91d_11eb_aaae_0a43f95f28a3"
tableName := "mytbl"
countIterations := 5
toTableNames := map[string]bool{}
for i := 0; i < countIterations; i++ {
_, toTableName, err := GenerateRenameStatementWithUUID(tableName, PurgeTableGCState, OnlineDDLToGCUUID(uuid), time.Now().Add(time.Duration(i)*time.Second).UTC())
require.NoError(t, err)
toTableNames[toTableName] = true
}
assert.Equal(t, countIterations, len(toTableNames))
}
41 changes: 23 additions & 18 deletions go/vt/vttablet/onlineddl/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,15 +420,9 @@ func (e *Executor) dropOnlineDDLUser(ctx context.Context) error {

// tableExists checks if a given table exists.
func (e *Executor) tableExists(ctx context.Context, tableName string) (bool, error) {
conn, err := e.pool.Get(ctx)
if err != nil {
return false, err
}
defer conn.Recycle()

tableName = strings.ReplaceAll(tableName, `_`, `\_`)
parsed := sqlparser.BuildParsedQuery(sqlShowTablesLike, tableName)
rs, err := conn.Exec(ctx, parsed.Query, 1, true)
rs, err := e.execQuery(ctx, parsed.Query)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -2350,6 +2344,10 @@ func (e *Executor) reviewStaleMigrations(ctx context.Context) error {
if err := e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed); err != nil {
return err
}
_ = e.updateMigrationStartedTimestamp(ctx, uuid)
if err := e.updateMigrationTimestamp(ctx, "completed_timestamp", uuid); err != nil {
return err
}
_ = e.updateMigrationMessage(ctx, onlineDDL.UUID, "stale migration")
}

Expand All @@ -2364,7 +2362,7 @@ func (e *Executor) retryTabletFailureMigrations(ctx context.Context) error {
}

// gcArtifactTable garbage-collects a single table
func (e *Executor) gcArtifactTable(ctx context.Context, artifactTable, uuid string) error {
func (e *Executor) gcArtifactTable(ctx context.Context, artifactTable, uuid string, t time.Time) error {
tableExists, err := e.tableExists(ctx, artifactTable)
if err != nil {
return err
Expand All @@ -2374,17 +2372,11 @@ func (e *Executor) gcArtifactTable(ctx context.Context, artifactTable, uuid stri
}
// We've already concluded in gcArtifacts() that this table was held for long enough.
// We therefore move it into PURGE state.
renameStatement, _, err := schema.GenerateRenameStatementWithUUID(artifactTable, schema.PurgeTableGCState, schema.OnlineDDLToGCUUID(uuid), time.Now().UTC())
if err != nil {
return err
}
conn, err := e.pool.Get(ctx)
renameStatement, _, err := schema.GenerateRenameStatementWithUUID(artifactTable, schema.PurgeTableGCState, schema.OnlineDDLToGCUUID(uuid), t)
if err != nil {
return err
}
defer conn.Recycle()

_, err = conn.Exec(ctx, renameStatement, 1, true)
_, err = e.execQuery(ctx, renameStatement)
return err
}

Expand All @@ -2393,6 +2385,13 @@ func (e *Executor) gcArtifacts(ctx context.Context) error {
e.migrationMutex.Lock()
defer e.migrationMutex.Unlock()

if _, err := e.execQuery(ctx, sqlFixCompletedTimestamp); err != nil {
// This query fixes a bug where stale migrations were marked as 'failed' without updating 'completed_timestamp'
// see https://github.com/vitessio/vitess/issues/8499
// Running this query retroactively sets completed_timestamp
// This 'if' clause can be removed in version v13
return err
}
query, err := sqlparser.ParseAndBind(sqlSelectUncollectedArtifacts,
sqltypes.Int64BindVariable(int64((*retainOnlineDDLTables).Seconds())),
)
Expand All @@ -2408,8 +2407,14 @@ func (e *Executor) gcArtifacts(ctx context.Context) error {
artifacts := row["artifacts"].ToString()

artifactTables := textutil.SplitDelimitedList(artifacts)
for _, artifactTable := range artifactTables {
if err := e.gcArtifactTable(ctx, artifactTable, uuid); err != nil {

timeNow := time.Now()
for i, artifactTable := range artifactTables {
// We wish to generate distinct timestamp values for each table in this UUID,
// because all tables will be renamed as _something_UUID_timestamp. Since UUID
// is shared for all artifacts in this loop, we differentiate via timestamp
t := timeNow.Add(time.Duration(i) * time.Second).UTC()
if err := e.gcArtifactTable(ctx, artifactTable, uuid, t); err != nil {
return err
}
log.Infof("Executor.gcArtifacts: renamed away artifact %s", artifactTable)
Expand Down
15 changes: 12 additions & 3 deletions go/vt/vttablet/onlineddl/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ const (
WHERE
migration_uuid=%a
`
sqlUpdateMigrationStartedTimestamp = `UPDATE _vt.schema_migrations
SET started_timestamp=IFNULL(started_timestamp, NOW())
sqlUpdateMigrationStartedTimestamp = `UPDATE _vt.schema_migrations SET
started_timestamp =IFNULL(started_timestamp, NOW()),
liveness_timestamp=IFNULL(liveness_timestamp, NOW())
WHERE
migration_uuid=%a
`
Expand All @@ -128,7 +129,7 @@ const (
migration_uuid=%a
`
sqlUpdateArtifacts = `UPDATE _vt.schema_migrations
SET artifacts=concat(%a, ',', artifacts)
SET artifacts=concat(%a, ',', artifacts), cleanup_timestamp=NULL
WHERE
migration_uuid=%a
`
Expand Down Expand Up @@ -263,6 +264,14 @@ const (
AND cleanup_timestamp IS NULL
AND completed_timestamp <= NOW() - INTERVAL %a SECOND
`
sqlFixCompletedTimestamp = `UPDATE _vt.schema_migrations
SET
completed_timestamp=NOW()
WHERE
migration_status='failed'
AND cleanup_timestamp IS NULL
AND completed_timestamp IS NULL
`
sqlSelectMigration = `SELECT
id,
migration_uuid,
Expand Down

0 comments on commit b0a094d

Please sign in to comment.