[FLINK-40623][cdc-base] Release chunk splitter JDBC connection once a table is split - #4534
Merged
loserwang1024 merged 3 commits intoSep 21, 2026
Conversation
|
|
||
| /** Generates all snapshot splits (chunks) for the give table path. */ | ||
| @Override | ||
| public Collection<SnapshotSplit> generateSplits(TableId tableId) throws Exception { |
Contributor
There was a problem hiding this comment.
What about using temp jdbc connection each time for generateSplits and release immediately. code is more clean.
Suggested change
| public Collection<SnapshotSplit> generateSplits(TableId tableId) throws Exception { | |
| @Override | |
| public Collection<SnapshotSplit> generateSplits(TableId tableId) throws Exception { | |
| try (JdbcConnection jdbcConnection = dialect.openJdbcConnection(sourceConfig)){ | |
| return generateSplits(tableId, jdbcConnection); | |
| } | |
| } | |
| private Collection<SnapshotSplit> generateSplits(TableId tableId, JdbcConnection jdbcConnection) throws Exception { | |
| if (!hasNextChunk()) { | |
| // split a new table. | |
| analyzeTable(tableId, jdbcConnection); | |
| Optional<List<SnapshotSplit>> evenlySplitChunks = trySplitAllEvenlySizedChunks(tableId); | |
| if (evenlySplitChunks.isPresent()) { | |
| return evenlySplitChunks.get(); | |
| } else { | |
| synchronized (lock) { | |
| this.currentSplittingTableId = tableId; | |
| this.nextChunkStart = ChunkSplitterState.ChunkBound.START_BOUND; | |
| this.nextChunkId = 0; | |
| return Collections.singletonList(splitOneUnevenlySizedChunk(tableId, jdbcConnection)); | |
| } | |
| } | |
| } else { | |
| Preconditions.checkState( | |
| currentSplittingTableId.equals(tableId), | |
| "Can not split a new table before the previous table splitting finish."); | |
| if (currentSplittingTable == null) { | |
| analyzeTable(currentSplittingTableId, jdbcConnection); | |
| } | |
| synchronized (lock) { | |
| return Collections.singletonList(splitOneUnevenlySizedChunk(tableId, jdbcConnection)); | |
| } | |
| } | |
| } |
Contributor
Author
There was a problem hiding this comment.
Done, thanks for the suggestion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of this pull request?
Fixes FLINK-40623: every incremental-snapshot JDBC source (Postgres, Oracle, SQL Server, Db2) keeps one JDBC connection open on the JobManager for the whole lifetime of the job.
Since FLINK-34688 (asynchronous chunk splitting),
JdbcSourceChunkSplitter#open()acquires a connection fromJdbcConnectionPoolsand onlyclose()releases it. The splitter is only needed while a table is being split into chunks, but the enumerator keeps it alive until the job ends, so the connection stays checked out during the entire streaming phase.JdbcConnectionPoolsis a JVM-wide singleton keyed by host/port/user/database with a defaultconnection.pool.sizeof 20, so on a session cluster the 21st job against the same database fails at submission with:This is not fixable from the job side:
connection.pool.sizeis only honoured by whichever job creates the pool first, anddebezium.connect.pool.sizeis not read by the pool at all.Brief change log
JdbcSourceChunkSplitter#generateSplitsborrows a pooled connection with try-with-resources and returns it when the call ends.analyzeTableandsplitOneUnevenlySizedChunktake that connection as a parameter.open()andclose()have nothing to acquire or release, and a splitter that has nothing left to split (e.g. restored after the snapshot phase) holds no connection.generateSplitscall, the connection is now borrowed and returned per chunk instead of being held until the job ends.JdbcSourceChunkSplitterTest#testConnectionIsReleasedWhenEvenlySizedTableIsSplitand#testConnectionIsReleasedAfterEachUnevenlySizedChunk.Other chunk splitters (
MySqlChunkSplitter, MongoDB) do not extendJdbcSourceChunkSplitterand are unaffected.Verifying this change
This change added tests and can be verified as follows:
flink-cdc-base:testConnectionIsReleasedWhenEvenlySizedTableIsSplitasserts thatopen()does not open a connection, and that splitting an evenly sized table opens and closes exactly one connection.testConnectionIsReleasedAfterEachUnevenlySizedChunksplits an unevenly sized table in two calls and asserts that each call opens and closes its own connection, so none is held between calls.postgres-cdcjobs (incremental snapshot enabled) against one PostgreSQL database, defaultconnection.pool.size(20):flink-sql-connector-postgres-cdc): all 30 jobs submitted from a fresh snapshot, JobManager connections dropped to 1 once splitting finished, TaskManager connections unchanged, noHikariPoolerrors, checkpoints completing for all jobs, and a row updated in the source table arrived in the sink within seconds.Documentation
Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Claude Fable 5.1)
🤖 Generated with Claude Code