diff --git a/br/pkg/restore/snap_client/client.go b/br/pkg/restore/snap_client/client.go index e7b283dd92fc4..df937355ec020 100644 --- a/br/pkg/restore/snap_client/client.go +++ b/br/pkg/restore/snap_client/client.go @@ -172,7 +172,7 @@ type SnapClient struct { // restore from a checkpoint inherits the same restoreUUID. restoreUUID uuid.UUID - checkPrivilegeTableRowsCollateCompatiblity bool + privilegeTableRowsCollateCompatibility bool } // NewRestoreClient returns a new RestoreClient. @@ -275,16 +275,16 @@ func (rc *SnapClient) GetSupportPolicy() bool { return rc.supportPolicy } -// SetCheckPrivilegeTableRowsCollateCompatiblity set switch to check +// SetCheckPrivilegeTableRowsCollateCompatibility set switch to check // privilege tables with different collate columns -func (rc *SnapClient) SetCheckPrivilegeTableRowsCollateCompatiblity(v bool) { - rc.checkPrivilegeTableRowsCollateCompatiblity = v +func (rc *SnapClient) SetCheckPrivilegeTableRowsCollateCompatibility(v bool) { + rc.privilegeTableRowsCollateCompatibility = v } -// GetCheckPrivilegeTableRowsCollateCompatiblity get switch to check +// GetCheckPrivilegeTableRowsCollateCompatibility get switch to check // privilege tables with different collate columns -func (rc *SnapClient) GetCheckPrivilegeTableRowsCollateCompatiblity() bool { - return rc.checkPrivilegeTableRowsCollateCompatiblity +func (rc *SnapClient) GetCheckPrivilegeTableRowsCollateCompatibility() bool { + return rc.privilegeTableRowsCollateCompatibility } func (rc *SnapClient) updateConcurrency() { diff --git a/br/pkg/restore/snap_client/systable_restore.go b/br/pkg/restore/snap_client/systable_restore.go index 554d1291476f0..c046ae74edb9d 100644 --- a/br/pkg/restore/snap_client/systable_restore.go +++ b/br/pkg/restore/snap_client/systable_restore.go @@ -146,13 +146,13 @@ var unRecoverableTable = map[string]map[string]struct{}{ }, } -type checkPrivilegeTableRowsCollateCompatiblitySQLPair struct { +type checkPrivilegeTableRowsCollateCompatibilitySQLPair struct { upstreamCollateSQL string downstreamCollateSQL string columns map[string]struct{} } -var collateCompatibilityTables = map[string]map[string]checkPrivilegeTableRowsCollateCompatiblitySQLPair{ +var collateCompatibilityTables = map[string]map[string]checkPrivilegeTableRowsCollateCompatibilitySQLPair{ "mysql": { "db": { upstreamCollateSQL: "SELECT COUNT(1) FROM __TiDB_BR_Temporary_mysql.db", @@ -531,7 +531,7 @@ func (rc *SnapClient) replaceTemporaryTableToSystable(ctx context.Context, ti *m log.Info("replace into existing table", zap.String("table", tableName), zap.Stringer("schema", db.Name)) - if rc.checkPrivilegeTableRowsCollateCompatiblity { + if rc.privilegeTableRowsCollateCompatibility { if err := rc.checkPrivilegeTableRowsCollateCompatibility(ctx, dbName, tableName, ti, db.ExistingTables[tableName]); err != nil { return err } @@ -607,11 +607,17 @@ func CheckSysTableCompatibility(dom *domain.Domain, tables []*metautil.Table, co col := ti.Columns[i] backupCol := backupColMap[col.Name.L] if backupCol == nil { - // skip when the backed up mysql.user table is missing columns. + // mysql.user may gain new columns in newer TiDB versions. In that case the + // schemas are still logically compatible, but loading the backed-up data + // directly into the temporary table with the newer schema can fail checksum + // validation because the upstream snapshot does not contain the new column. + // Fall back to non-physical loading for mysql.user when the backup is + // missing target columns. if backupTi.Name.L == sysUserTableName { log.Warn("missing column in backup data", zap.Stringer("table", table.Info.Name), zap.String("col", fmt.Sprintf("%s %s", col.Name, col.FieldType.String()))) + canLoadSysTablePhysical = false continue } log.Error("missing column in backup data", @@ -688,11 +694,11 @@ func (rc *SnapClient) checkPrivilegeTableRowsCollateCompatibility( dbNameL, tableNameL string, upstreamTable, downstreamTable *model.TableInfo, ) error { - collateCompatiblityTableMap, exists := collateCompatibilityTables[dbNameL] + collateCompatibilityTableMap, exists := collateCompatibilityTables[dbNameL] if !exists { return nil } - collateCompatibilityColumnMap, exists := collateCompatiblityTableMap[tableNameL] + collateCompatibilityColumnMap, exists := collateCompatibilityTableMap[tableNameL] if !exists { return nil } diff --git a/br/pkg/restore/snap_client/systable_restore_test.go b/br/pkg/restore/snap_client/systable_restore_test.go index 691293fb35a3e..13a5813e7669b 100644 --- a/br/pkg/restore/snap_client/systable_restore_test.go +++ b/br/pkg/restore/snap_client/systable_restore_test.go @@ -54,7 +54,7 @@ func TestCheckSysTableCompatibility(t *testing.T) { require.NoError(t, err) var canLoadSysTablePhysical bool - // user table in cluster have more columns(success) + // user table in cluster have more columns(failed) mockedUserTI := userTI.Clone() userTI.Columns = append(userTI.Columns, &model.ColumnInfo{Name: ast.NewCIStr("new-name")}) canLoadSysTablePhysical, err = snapclient.CheckSysTableCompatibility(cluster.Domain, []*metautil.Table{{ @@ -62,7 +62,7 @@ func TestCheckSysTableCompatibility(t *testing.T) { Info: mockedUserTI, }}, false) require.NoError(t, err) - require.True(t, canLoadSysTablePhysical) + require.False(t, canLoadSysTablePhysical) userTI.Columns = userTI.Columns[:len(userTI.Columns)-1] // user table in cluster have less columns(failed) @@ -233,7 +233,7 @@ func TestCheckPrivilegeTableRowsCollateCompatibility(t *testing.T) { defer rc.Close() err := rc.InitConnections(g, cluster.Storage) require.NoError(t, err) - rc.SetCheckPrivilegeTableRowsCollateCompatiblity(true) + rc.SetCheckPrivilegeTableRowsCollateCompatibility(true) se, err := g.CreateSession(cluster.Storage) require.NoError(t, err) diff --git a/br/pkg/task/restore.go b/br/pkg/task/restore.go index 5d5cb86f86db2..eb8e55cc73967 100644 --- a/br/pkg/task/restore.go +++ b/br/pkg/task/restore.go @@ -747,7 +747,7 @@ func configureRestoreClient(ctx context.Context, client *snapclient.SnapClient, client.SetPlacementPolicyMode(cfg.WithPlacementPolicy) client.SetWithSysTable(cfg.WithSysTable) client.SetRewriteMode(ctx) - client.SetCheckPrivilegeTableRowsCollateCompatiblity(cfg.SysCheckCollation) + client.SetCheckPrivilegeTableRowsCollateCompatibility(cfg.SysCheckCollation) return nil } @@ -1463,7 +1463,7 @@ func runSnapshotRestore(c context.Context, mgr *conn.Mgr, g glue.Glue, cmdName s } if client.IsFullClusterRestore() && client.HasBackedUpSysDB() { - canLoadSysTablePhysical, err := snapclient.CheckSysTableCompatibility(mgr.GetDomain(), tables, client.GetCheckPrivilegeTableRowsCollateCompatiblity()) + canLoadSysTablePhysical, err := snapclient.CheckSysTableCompatibility(mgr.GetDomain(), tables, client.GetCheckPrivilegeTableRowsCollateCompatibility()) if err != nil { return errors.Trace(err) } @@ -1471,9 +1471,9 @@ func runSnapshotRestore(c context.Context, mgr *conn.Mgr, g glue.Glue, cmdName s log.Info("The system tables schema is not compatible. Fallback to logically load system tables.") loadSysTablePhysical = false } - if client.GetCheckPrivilegeTableRowsCollateCompatiblity() && canLoadSysTablePhysical { + if client.GetCheckPrivilegeTableRowsCollateCompatibility() && canLoadSysTablePhysical { log.Info("The system tables schema match so no need to set sys check collation") - client.SetCheckPrivilegeTableRowsCollateCompatiblity(false) + client.SetCheckPrivilegeTableRowsCollateCompatibility(false) } }