ddl: fix affinity idempotency problem (#65291)

ref pingcap/tidb#64938
This commit is contained in:
lhy1024
2025-12-26 23:37:25 +08:00
committed by GitHub
parent 163790b780
commit 3056f41c48
2 changed files with 24 additions and 6 deletions

View File

@ -173,9 +173,12 @@ func checkAffinityGroupsInPD(t *testing.T, do *domain.Domain, dbName, tbName str
func TestAffinityPDInteraction(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2, tp1, tp2")
dropTable := func() {
tk.MustExec("drop table if exists t1, t2, t3, tp1, tp2, tp3")
}
dropTable()
defer dropTable()
// Test 1: Create table with affinity='table'
tk.MustExec("create table t1(a int) affinity = 'table'")
@ -237,8 +240,19 @@ func TestAffinityPDInteraction(t *testing.T) {
require.NoError(t, err)
require.Empty(t, groups, "old partition's affinity group should be deleted after truncate partition")
// Cleanup
tk.MustExec("drop table if exists t2, tp1, tp2")
// Test 8: ALTER TABLE AFFINITY idempotency - partition -> partition
tk.MustExec("create table tp3(a int) affinity = 'partition' partition by hash(a) partitions 3")
checkAffinityGroupsInPD(t, dom, "test", "tp3", true)
// Set affinity to partition again (idempotent operation)
tk.MustExec("alter table tp3 affinity = 'partition'")
checkAffinityGroupsInPD(t, dom, "test", "tp3", true)
// Test 9: ALTER TABLE AFFINITY idempotency - table -> table
tk.MustExec("create table t3(a int) affinity = 'table'")
checkAffinityGroupsInPD(t, dom, "test", "t3", true)
// Set affinity to table again (idempotent operation)
tk.MustExec("alter table t3 affinity = 'table'")
checkAffinityGroupsInPD(t, dom, "test", "t3", true)
}
func TestAffinityDropDatabase(t *testing.T) {

View File

@ -1778,9 +1778,13 @@ func onAlterTableAffinity(jobCtx *jobContext, job *model.Job) (ver int64, err er
// Delete old affinity groups (best-effort cleanup - ignore errors)
// ALTER TABLE AFFINITY: only delete when old table had affinity configuration
// This ensures 'ALTER TABLE AFFINITY = 'none'' correctly cleans up stale affinity groups
// Skip deletion if the affinity level remains the same to ensure idempotency
if oldTblInfo.Affinity != nil {
if err := deleteTableAffinityGroupsInPD(jobCtx, oldTblInfo, nil); err != nil {
logutil.DDLLogger().Error("failed to delete old affinity groups from PD", zap.Error(err), zap.Int64("tableID", oldTblInfo.ID))
// Only delete if affinity is removed or level changed (same level means same group IDs)
if tblInfo.Affinity == nil || oldTblInfo.Affinity.Level != tblInfo.Affinity.Level {
if err := deleteTableAffinityGroupsInPD(jobCtx, oldTblInfo, nil); err != nil {
logutil.DDLLogger().Error("failed to delete old affinity groups from PD", zap.Error(err), zap.Int64("tableID", oldTblInfo.ID))
}
}
}