Skip to content

Commit

Permalink
Merge pull request #8192 from planetscale/online-ddl-ghost-fatal-message
Browse files Browse the repository at this point in the history
Online DDL: read and publish gh-ost FATAL message where possible
  • Loading branch information
shlomi-noach authored Jun 3, 2021
2 parents 9b3c055 + c8cabfe commit e018d0f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 4 deletions.
23 changes: 23 additions & 0 deletions go/test/endtoend/onlineddl/ghost/onlineddl_ghost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ var (
online_ddl_create_col INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;`
noPKCreateTableStatement = `
CREATE TABLE %s (
online_ddl_create_col INT NOT NULL
) ENGINE=InnoDB;`
onlineDDLDropTableStatement = `
DROP TABLE %s`
onlineDDLDropTableIfExistsStatement = `
Expand Down Expand Up @@ -289,6 +293,25 @@ func TestSchemaChange(t *testing.T) {
onlineddl.CheckCancelMigration(t, &vtParams, shards, uuid, false)
onlineddl.CheckRetryMigration(t, &vtParams, shards, uuid, true)
})
t.Run("Online CREATE no PK table, vtgate", func(t *testing.T) {
uuid := testOnlineDDLStatement(t, noPKCreateTableStatement, "gh-ost --skip-topo", "vtgate", "online_ddl_create_col")
onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusComplete)
onlineddl.CheckCancelMigration(t, &vtParams, shards, uuid, false)
onlineddl.CheckRetryMigration(t, &vtParams, shards, uuid, false)
})
t.Run("Fail ALTER for no PK table, vtgate", func(t *testing.T) {
uuid := testOnlineDDLStatement(t, alterTableTrivialStatement, "gh-ost --skip-topo", "vtgate", "")
onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusFailed)

rs := onlineddl.ReadMigrations(t, &vtParams, uuid)
require.NotNil(t, rs)
for _, row := range rs.Named().Rows {
message := row["message"].ToString()
// the following message is generated by gh-ost. We test that it is captured in our 'message' column:
expectedMessage := "No PRIMARY nor UNIQUE key found"
require.Contains(t, message, expectedMessage)
}
})
}

func testWithInitialSchema(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions go/test/endtoend/onlineddl/vtgate_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,13 @@ func CheckMigrationArtifacts(t *testing.T, vtParams *mysql.ConnParams, shards []
assert.Equal(t, expectArtifacts, hasArtifacts)
}
}

// ReadMigrations reads migration entries
func ReadMigrations(t *testing.T, vtParams *mysql.ConnParams, like string) *sqltypes.Result {
query, err := sqlparser.ParseAndBind("show vitess_migrations like %a",
sqltypes.StringBindVariable(like),
)
require.NoError(t, err)

return VtgateExecQuery(t, vtParams, query, "")
}
23 changes: 19 additions & 4 deletions go/vt/vttablet/onlineddl/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,10 @@ const (
)

var (
migrationLogFileName = "migration.log"
onlineDDLUser = "vt-online-ddl-internal"
onlineDDLGrant = fmt.Sprintf("'%s'@'%s'", onlineDDLUser, "%")
migrationLogFileName = "migration.log"
migrationFailureFileName = "migration-failure.log"
onlineDDLUser = "vt-online-ddl-internal"
onlineDDLGrant = fmt.Sprintf("'%s'@'%s'", onlineDDLUser, "%")
)

type mysqlVariables struct {
Expand Down Expand Up @@ -879,12 +880,16 @@ password=${ONLINE_DDL_PASSWORD}
wrapperScriptContent := fmt.Sprintf(`#!/bin/bash
ghost_log_path="%s"
ghost_log_file="%s"
ghost_log_failure_file="%s"
mkdir -p "$ghost_log_path"
export ONLINE_DDL_PASSWORD
%s "$@" > "$ghost_log_path/$ghost_log_file" 2>&1
`, tempDir, migrationLogFileName, binaryFileName,
exit_code=$?
grep -o '\bFATAL\b.*' "$ghost_log_path/$ghost_log_file" | tail -1 > "$ghost_log_path/$ghost_log_failure_file"
exit $exit_code
`, tempDir, migrationLogFileName, migrationFailureFileName, binaryFileName,
)
wrapperScriptFileName, err := createTempScript(tempDir, "gh-ost-wrapper.sh", wrapperScriptContent)
if err != nil {
Expand Down Expand Up @@ -984,6 +989,16 @@ export ONLINE_DDL_PASSWORD
_ = e.updateMigrationMessage(ctx, onlineDDL.UUID, fmt.Sprintf("executing gh-ost --execute=%v", execute))
_, err := execCmd("bash", args, os.Environ(), "/tmp", nil, nil)
_ = e.updateMigrationMessage(ctx, onlineDDL.UUID, fmt.Sprintf("executed gh-ost --execute=%v, err=%v", execute, err))
if err != nil {
// See if we can get more info from the failure file
if content, ferr := ioutil.ReadFile(path.Join(tempDir, migrationFailureFileName)); ferr == nil {
failureMessage := strings.TrimSpace(string(content))
if failureMessage != "" {
// This message was produced by gh-ost itself. It is more informative than the default "migration failed..." message. Overwrite.
return errors.New(failureMessage)
}
}
}
return err
}

Expand Down

0 comments on commit e018d0f

Please sign in to comment.