Skip to content

fix: DeltaAppender cleanup on rollback#5421

Open
drrtuy wants to merge 2 commits into
MariaDB:11.4from
drrtuy:bb-11.4-delta-cleanup
Open

fix: DeltaAppender cleanup on rollback#5421
drrtuy wants to merge 2 commits into
MariaDB:11.4from
drrtuy:bb-11.4-delta-cleanup

Conversation

@drrtuy

@drrtuy drrtuy commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Fix DuckDB transaction cleanup and plugin initialization

What

Prevent buffered DuckDB writes from surviving rollback or connection teardown, and make plugin initialization fail safely instead of propagating exceptions into MariaDB.

Key changes

  • Discard buffered DeltaAppender data without flushing during rollback, disconnect, or appender removal.
  • Reset per-session appenders before rolling back the DuckDB transaction.
  • Propagate DuckDB BEGIN failures and register the storage engine only after the transaction starts successfully.
  • Add MTR coverage for rollback and disconnect with pending batch inserts.
  • Validate initialization SQL and catch failures from connection setup, compatibility function registration, and cross-engine scan registration.
  • Release partially initialized DuckDB state when plugin initialization fails.

How to test

Run:

./mtr --suite=duckdb --force --force

Expected result: all enabled DuckDB tests pass, including duckdb.batch_rollback and duckdb.batch_disconnect.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves transaction management, error handling, and resource cleanup in the DuckDB storage engine. Key changes include early transaction registration with error handling, discarding appenders during rollback, wrapping database initialization in try-catch blocks with robust error checking, and adding test cases for batch disconnects and rollbacks. Feedback suggests wrapping the destructor's rollback call in a try-catch block to prevent potential server crashes from unhandled exceptions, and avoiding passing a std::string directly to a %s format specifier in exception constructors to prevent undefined behavior.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 51 to 55
~DuckdbThdContext()
{
if (has_transaction())
{
std::string error_msg;
duckdb_trans_rollback(error_msg);
}
std::string error_msg;
duckdb_trans_rollback(error_msg);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Destructors in C++ should not allow exceptions to propagate, as doing so will trigger std::terminate() and crash the server. Since DuckDB operations (such as those called within duckdb_trans_rollback) can throw exceptions (e.g., duckdb::Exception), it is safer to wrap the rollback call in a try-catch block to ensure any exceptions are caught and handled gracefully.

  ~DuckdbThdContext()
  {
    try
    {
      std::string error_msg;
      duckdb_trans_rollback(error_msg);
    }
    catch (...)
    {
      // Ignore exceptions in destructor to prevent std::terminate
    }
  }

Comment thread storage/duckdb/runtime/duckdb_manager.cc

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the DuckDB storage engine integration by ensuring buffered batch writes are discarded (not flushed) on rollback/disconnect and by making DuckDB plugin initialization fail safely without leaking partially initialized state.

Changes:

  • Add explicit discard paths for DeltaAppender buffers, and invoke discard/reset before DuckDB rollback and appender removal.
  • Make transaction begin failures propagate back to MariaDB, and gate engine registration on a successful DuckDB BEGIN.
  • Add new MTR tests covering rollback/disconnect behavior with pending batch inserts.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
storage/duckdb/runtime/duckdb_manager.cc Wrap initialization steps in exception handling and clean up DuckDB state on failure.
storage/duckdb/runtime/duckdb_context.h Reset/discard per-session appenders before rollback; propagate BEGIN error text.
storage/duckdb/runtime/delta_appender.h Add discard() / discard_all() APIs to drop buffered rows without flushing.
storage/duckdb/runtime/delta_appender.cc Implement discard logic and ensure discard occurs before appender removal/teardown.
storage/duckdb/mysql-test/duckdb/t/batch_rollback.test Add MTR coverage for rollback with pending batched inserts.
storage/duckdb/mysql-test/duckdb/t/batch_disconnect.test Add MTR coverage for disconnect with pending batched inserts.
storage/duckdb/ha_duckdb.cc Ensure DuckDB transaction begins successfully before registering the handlerton in the transaction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +197 to +200
if (result->HasError())
throw duckdb::InvalidInputException(
"DuckDB initialization query failed: %s", result->GetError());
};
Comment on lines 104 to 105
if (!m_con)
return true;
Comment thread storage/duckdb/mysql-test/duckdb/t/batch_rollback.test
Comment thread storage/duckdb/mysql-test/duckdb/t/batch_disconnect.test
@drrtuy
drrtuy force-pushed the bb-11.4-delta-cleanup branch from e9efb13 to f7d25ec Compare July 21, 2026 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants