risingwavelabs/risingwave · critical

implement MySQL CDC parallelized backfill

Error message

implement MySQL CDC parallelized backfill

What it means

split_snapshot_read on the MySQL external table reader is an unimplemented stub: it immediately panics with todo!. Parallelized (split-key based) CDC backfill for MySQL is not yet implemented, so calling this path aborts the stream task.

Source

Thrown at src/connector/src/source/cdc/external/mysql.rs:522

        self.pool.disconnect().await.map_err(|e| e.into())
    }

    fn get_parallel_cdc_splits(
        &self,
        _options: CdcTableSnapshotSplitOption,
    ) -> BoxStream<'_, ConnectorResult<CdcTableSnapshotSplit>> {
        // TODO(zw): feat: impl
        stream::empty::<ConnectorResult<CdcTableSnapshotSplit>>().boxed()
    }

    fn split_snapshot_read(
        &self,
        _table_name: SchemaTableName,
        _left: OwnedRow,
        _right: OwnedRow,
        _split_columns: Vec<Field>,
    ) -> BoxStream<'_, ConnectorResult<OwnedRow>> {
        todo!("implement MySQL CDC parallelized backfill")
    }
}

impl MySqlExternalTableReader {
    /// Get MySQL version from the connection
    async fn get_mysql_version(pool: &mysql_async::Pool) -> ConnectorResult<(u8, u8, bool)> {
        let mut conn = pool.get_conn().await?;
        let result: Option<String> = conn.query_first("SELECT VERSION()").await?;

        if let Some(version_str) = result {
            let parts: Vec<&str> = version_str.split('.').collect();
            if parts.len() >= 2 {
                let major_version = parts[0]
                    .parse::<u8>()
                    .context("Failed to parse major version")?;
                let minor_version = parts[1]
                    .parse::<u8>()
                    .context("Failed to parse minor version")?;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Do not configure parallel split-based backfill for MySQL CDC; use the default single-threaded snapshot path.
  2. Upgrade RisingWave to a version where MySQL parallel backfill is implemented.
  3. If you maintain the code, implement the method (range-query rows between _left and _right on _split_columns) or route to the non-split reader.
  4. File an issue / check the tracker for 'MySQL CDC parallelized backfill' progress.

Example fix

// before
fn split_snapshot_read(...) -> ... {
    todo!("implement MySQL CDC parallelized backfill")
}
// after
fn split_snapshot_read(...) -> ... {
    self.stream_snapshot_read(...) // fall back to non-parallel snapshot read
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Prefer the non-split snapshot path when using MySQL CDC:
let use_parallel_backfill = false; // MySQL parallelized backfill is unimplemented
if connector == "mysql-cdc" && use_parallel_backfill {
    return Err("MySQL CDC does not support parallel split-based backfill".into());
}

Try / catch

match reader.split_snapshot_read(table, left, right, cols).await.next().await {
    Some(Err(e)) if e.to_string().contains("parallelized backfill") || e.to_string().contains("not implemented") => {
        eprintln!("Falling back to sequential snapshot read");
        reader.snapshot_read(table).await
    }
    other => other,
}

Prevention

When it happens

Trigger: The backfill planner assigns a split-based parallel snapshot read for a MySQL CDC table, invoking MySqlExternalTableReader::split_snapshot_read with left/right split rows.

Common situations: Users enabling parallel/serialized split backfill options on MySQL CDC sources; developers exercising the external-table reader API directly in tests.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/e5ef79fa7cc99320. Report an issue: GitHub.