Skip to content

Commit acc2b74

Browse files
fix(clickhouse): drop orphaned shard table after mirror resync exchange
After EXCHANGE TABLES during resync, the original Distributed table is dropped but the local shard it referenced (e.g. itunes_apps_shard) was never cleaned up. Resolve the shard name from the Distributed table definition before the exchange, then drop it after the exchange succeeds.
1 parent 4ff837b commit acc2b74

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

  • flow/connectors/clickhouse

flow/connectors/clickhouse/cdc.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,18 @@ func (c *ClickHouseConnector) RenameTables(
331331
}
332332

333333
if originalTableExists {
334+
// Before swapping, resolve the shard table that the original Distributed table currently points to.
335+
// After the EXCHANGE the Distributed table is dropped, leaving that shard orphaned unless we drop it explicitly.
336+
var originalShardTable string
337+
if c.Config.Cluster != "" {
338+
originalShardTable, err = c.getDistributedShardTable(ctx, renameRequest.NewName)
339+
if err != nil {
340+
c.logger.Warn("could not resolve shard table for original distributed table, old shard may be left behind",
341+
slog.String("table", renameRequest.NewName), slog.Any("error", err))
342+
originalShardTable = ""
343+
}
344+
}
345+
334346
// target table exists, so we can attempt to swap. In most cases, we will have Atomic engine,
335347
// which supports a special query to exchange two tables, allowing dependent (materialized) views and dictionaries on these tables
336348
c.logger.Info("attempting atomic exchange",
@@ -344,6 +356,15 @@ func (c *ClickHouseConnector) RenameTables(
344356
); err != nil {
345357
return nil, fmt.Errorf("unable to drop exchanged table %s: %w", renameRequest.CurrentName, err)
346358
}
359+
// Drop the original shard table that is now orphaned after the Distributed table was exchanged and dropped.
360+
if originalShardTable != "" {
361+
if err := c.execWithLogging(ctx,
362+
fmt.Sprintf(dropTableSQLWithCHSetting, peerdb_clickhouse.QuoteIdentifier(originalShardTable), onCluster),
363+
); err != nil {
364+
return nil, fmt.Errorf("unable to drop orphaned shard table %s: %w", originalShardTable, err)
365+
}
366+
c.logger.Info("dropped orphaned shard table after resync exchange", slog.String("shardTable", originalShardTable))
367+
}
347368
} else if ex, ok := err.(*clickhouse.Exception); !ok || chproto.Error(ex.Code) != chproto.ErrNotImplemented {
348369
// move on to the fallback code if unimplemented, in all other error codes / types return,
349370
// since we know/assume exchange would be the sensible action

0 commit comments

Comments
 (0)