@@ -305,15 +305,32 @@ private void startAsynchronouslySplit() {
305305 private void splitTable (TableId nextTable ) {
306306 LOG .info ("Start splitting table {} into chunks..." , nextTable );
307307 long start = System .currentTimeMillis ();
308+ long lastProgressTime = System .currentTimeMillis ();
308309 int chunkNum = 0 ;
309310 boolean hasRecordSchema = false ;
310311 // split the given table into chunks (snapshot splits)
311312 do {
312313 synchronized (lock ) {
313314 List <MySqlSnapshotSplit > splits ;
314315 try {
316+ // Add progress logging
317+ long now = System .currentTimeMillis ();
318+ if (now - lastProgressTime > 60000L ) { // Log every minute
319+ LOG .info (
320+ "Still splitting table {}, chunks generated so far: {}, elapsed time: {}ms" ,
321+ nextTable ,
322+ chunkNum ,
323+ now - start );
324+ lastProgressTime = now ;
325+ }
326+
315327 splits = chunkSplitter .splitChunks (partition , nextTable );
316328 } catch (Exception e ) {
329+ LOG .error (
330+ "Error when splitting chunks for table {}: {}" ,
331+ nextTable ,
332+ e .getMessage (),
333+ e );
317334 throw new IllegalStateException (
318335 "Error when splitting chunks for " + nextTable , e );
319336 }
@@ -367,13 +384,63 @@ public Optional<MySqlSplit> getNext() {
367384 split .toMySqlSnapshotSplit (tableSchemas .get (split .getTableId ())));
368385 } else if (!remainingTables .isEmpty ()) {
369386 try {
370- // wait for the asynchronous split to complete
371- lock .wait ();
387+ // wait for the asynchronous split to complete with timeout
388+ final long timeout = 30000L ; // 30 seconds timeout
389+ lock .wait (timeout );
390+
391+ // Check if we timed out and still have no splits
392+ if (remainingSplits .isEmpty () && !remainingTables .isEmpty ()) {
393+ LOG .warn (
394+ "Timeout waiting for asynchronous split generation, remaining tables: {}" ,
395+ remainingTables );
396+ // Try to restart the splitting process
397+ startAsynchronouslySplit ();
398+ // Wait again with shorter timeout
399+ lock .wait (5000L );
400+
401+ // After restart and wait, check again for splits
402+ if (!remainingSplits .isEmpty ()) {
403+ // Splits are now available after restart
404+ Iterator <MySqlSchemalessSnapshotSplit > iterator =
405+ remainingSplits .iterator ();
406+ MySqlSchemalessSnapshotSplit split = iterator .next ();
407+ remainingSplits .remove (split );
408+ assignedSplits .put (split .splitId (), split );
409+ addAlreadyProcessedTablesIfNotExists (split .getTableId ());
410+ return Optional .of (
411+ split .toMySqlSnapshotSplit (
412+ tableSchemas .get (split .getTableId ())));
413+ } else if (!remainingTables .isEmpty ()) {
414+ // Still no splits after restart, but we have tables - recurse normally
415+ return getNext ();
416+ } else {
417+ // No tables left after restart
418+ closeExecutorService ();
419+ return Optional .empty ();
420+ }
421+ }
422+ // If we didn't timeout (normal case), check if splits are available now
423+ if (!remainingSplits .isEmpty ()) {
424+ Iterator <MySqlSchemalessSnapshotSplit > iterator =
425+ remainingSplits .iterator ();
426+ MySqlSchemalessSnapshotSplit split = iterator .next ();
427+ remainingSplits .remove (split );
428+ assignedSplits .put (split .splitId (), split );
429+ addAlreadyProcessedTablesIfNotExists (split .getTableId ());
430+ return Optional .of (
431+ split .toMySqlSnapshotSplit (tableSchemas .get (split .getTableId ())));
432+ } else if (!remainingTables .isEmpty ()) {
433+ // No splits yet but still have tables to process - recurse
434+ return getNext ();
435+ } else {
436+ // No tables left
437+ closeExecutorService ();
438+ return Optional .empty ();
439+ }
372440 } catch (InterruptedException e ) {
373441 throw new FlinkRuntimeException (
374442 "InterruptedException while waiting for asynchronously snapshot split" );
375443 }
376- return getNext ();
377444 } else {
378445 closeExecutorService ();
379446 return Optional .empty ();
0 commit comments