João Boto created FLINK-40538:
---------------------------------

             Summary: [Postgres] Connector never starts streaming on a database 
with no publication traffic
                 Key: FLINK-40538
                 URL: https://issues.apache.org/jira/browse/FLINK-40538
             Project: Flink
          Issue Type: Bug
          Components: Flink CDC
    Affects Versions: cdc-3.6.0
            Reporter: João Boto
             Fix For: cdc-3.6.0


### Search before asking
- [x] I searched in the issues and found nothing similar.

### Flink version / Flink CDC version
Flink 2.2.1, Flink CDC 3.6.0 (`flink-connector-postgres-cdc`), Debezium 
1.9.8.Final,
PostgreSQL 18 (not version-specific).

### What happened

A Postgres CDC source pointed at a database that receives no writes to its 
publication
never leaves Debezium's WAL position search. It never begins streaming, and:

- no change events are ever produced (including once writes eventually start, 
until the
  first of them arrives);
- `heartbeat.action.query` never executes, so `heartbeat.interval.ms` has no 
effect;
- the replication slot's `confirmed_flush_lsn` never advances, so PostgreSQL 
retains
  every WAL segment from the slot's position for as long as the job runs.

The last point is the damaging one: the job reports RUNNING and healthy while 
WAL grows
without bound on the source database.

### How to reproduce

1. Create a Postgres CDC source over a schema whose tables receive no writes.
2. Start the job. Other databases in the cluster may be active; the captured
   publication must be quiet.
3. Observe the job is RUNNING, all checkpoints complete, and `numRecordsOut` of 
the
   source is 0.
4. Observe `confirmed_flush_lsn` in `pg_replication_slots` stays fixed while
   `pg_current_wal_lsn()` advances.
5. Write any row to a captured table — the connector immediately starts 
streaming and
   the slot begins advancing.

### Logs

At DEBUG for `io.debezium`, TRACE for
`io.debezium.connector.postgresql.connection`:

INFO  WalPositionLocator - Looking for WAL restart position for last commit LSN 
'null'
                           and last change LSN 'LSN\{0/518EB00}'
INFO  PostgresStreamingChangeEventSource - Searcion
TRACE PostgresReplicationConnection - Streaming requested from LSN 
LSN\{0/518EB00}, received LSN LSN\{0/5192A60}
TRACE PostgresReplicationConnection - Streaming 518EB00}, received LSN 
LSN\{0/5192AF0}
... repeats indefinitely, requested LSN never changes ...

`"WAL resume position '{}' discovered"` is never

### Cause

`PostgresSourceFetchTaskContext.loadStartingOffsetState` always returns a 
non-null
`PostgresOffsetContext`, built from the stream split's starting offset. In
`PostgresStreamingChangeEventSource#execute` that makes

```java
boolean hasStartLsnStoredInContext = offsetContext != null;

always true, so the WAL position search branch iPlain
Debezium takes the other branch on a fresh start and logs
"WAL position will not be searched".

searchWalPosition then loops until a message is  main
streaming loop — dispatches no heartbeat while waiting:

// searchWalPosition
if (receivedMessage) \{ noMessageIterations = 0; }
else {
    noMessageIterations++;                      vent
    ...
}

// main streaming loop
else {
    if (offsetContext.hasCompletelyProcessedPosition()) {
        dispatcher.dispatchHeartbeatEvent(partition, offsetContext);
    }
    ...
}

That is a deadlock: the search waits for publicay mechanism
that would generate traffic on an idle database — heartbeat.action.query, 
driven by
the heartbeat dispatch — runs only from the main loop, which the search 
precedes.

Possible fixes

1. Do not force the search when the stored offset has nothing processed yet, so
   Debezium takes the new WalPositionLocator() plot's
   confirmed position.
2. Write one WAL record when the stream task staates
   deterministically. We are running this as a l
   pg_logical_emit_message(false, '<internal prefix>', ...) in
   PostgresStreamFetchTask#execute before delega
   StreamSplitReadTask#execute. The prefix matchmessage, so
   the record is filtered before the sink.
3. Upstream Debezium: dispatch heartbeats in searchWalPosition as the main loop 
does.
   This would fix it without a change here, but g that fix.

Are you willing to submit a PR?

Yes.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to