Skip to content

Make table metadata addition atomic#3464

Draft
KodaiD wants to merge 4 commits into
masterfrom
make-metadata-addition-atomic
Draft

Make table metadata addition atomic#3464
KodaiD wants to merge 4 commits into
masterfrom
make-metadata-addition-atomic

Conversation

@KodaiD
Copy link
Copy Markdown
Member

@KodaiD KodaiD commented Apr 1, 2026

Description

This PR makes metadata addition in DDLs more robust.

TableMetadataService.addTableMetadata previously committed each SQL statement (DELETE and per-column INSERTs) individually. If a failure occurred mid-way, the table metadata could be left in an incomplete state. We can use repairTable in such a case, but it would be more robust if these metadata writes were executed atomically. This PR wraps the DELETE and all INSERTs in a single transaction to ensure atomicity.

Related issues and/or PRs

N/A

Changes made

  • Wrap the DELETE and all INSERT operations in TableMetadataService.addTableMetadata in a single transaction with explicit commit and rollback on failure.
  • Add verify(connection).commit() assertions to existing TableMetadataService.addTableMetadata unit tests.

Checklist

  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation to reflect the changes.
  • I have considered whether similar issues could occur in other products, components, or modules if this PR is for bug fixes.
  • Any remaining open issues linked to this PR are documented and up-to-date (Jira, GitHub, etc.).
  • Tests (unit, integration, etc.) have been added for the changes.
  • My changes generate no new warnings.
  • Any dependent changes in other PRs have been merged and published.

Additional notes (optional)

N/A

Release notes

Updated Admin to make multiple metadata writes atomic.

@KodaiD KodaiD self-assigned this Apr 1, 2026
Copy link
Copy Markdown
Contributor

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

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 introduces manual transaction management within the TableMetadataService.addTableMetadata method to ensure that metadata updates are atomic. The changes include logic to disable auto-commit, perform metadata operations, and handle commits or rollbacks, while restoring the original auto-commit state in a finally block. Corresponding unit tests in JdbcAdminTest were updated to verify the commit operation. Feedback was provided regarding a potential issue where calling commit() could unintentionally finalize an external transaction if the connection was already in a non-auto-commit state.

@KodaiD KodaiD marked this pull request as ready for review April 1, 2026 02:56
Copilot AI review requested due to automatic review settings April 1, 2026 02:56
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 aims to make JDBC table-metadata updates atomic by wrapping the delete+insert sequence in a single transaction, ensuring metadata isn’t left partially updated if an error occurs mid-operation.

Changes:

  • Updated TableMetadataService.addTableMetadata() to run metadata overwrite/insert operations within an explicit transaction and commit/rollback as a unit.
  • Adjusted JdbcAdminTest expectations to assert that a commit occurs after successful metadata additions.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
core/src/main/java/com/scalar/db/storage/jdbc/TableMetadataService.java Introduces explicit transaction boundaries (auto-commit toggle, commit/rollback) around metadata writes to make them atomic.
core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java Updates assertions to reflect the new commit behavior after adding table metadata.

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

Comment on lines +73 to +77
connection.commit();
} catch (SQLException e) {
try {
connection.rollback();
} catch (SQLException rollbackEx) {
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

addTableMetadata() unconditionally calls connection.commit() / connection.rollback() even when the caller already provided a connection with autoCommit=false (i.e., an existing transaction). That can unexpectedly commit/rollback the caller’s broader transaction and can also lead to redundant rollbacks when this method is invoked inside JdbcAdmin.withConnection() (which also rolls back on exceptions when requiresExplicitCommit is true). Consider committing/rolling back only when this method started the transaction (e.g., when originalAutoCommit was true), and when originalAutoCommit is false use a savepoint (rollback-to-savepoint on error) or leave commit/rollback to the caller.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In the current codebase, there are no uncommitted changes on the connection when addTableMetadata() is called. All prior operations within withConnection() lambda already commit individually via execute(connection, sql, requiresExplicitCommit). So the unconditional commit() here does not accidentally finalize someone else's work.

The redundant rollback (both addTableMetadata and withConnection rolling back on error) is harmless.

I want to keep the change scoped to addTableMetadata only, without modifying withConnection(), which is widely used across JdbcAdmin.

@brfrn169 What do you think?

Comment thread core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java
Comment thread core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java
Comment thread core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java
@KodaiD KodaiD requested review from a team, Torch3333, brfrn169, feeblefakie and komamitsu and removed request for a team April 1, 2026 07:16
Copy link
Copy Markdown
Member

@feeblefakie feeblefakie left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you!
Left one minor suggestion, so PTAL!

Comment on lines +60 to +62
if (originalAutoCommit) {
connection.setAutoCommit(false);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's minor, but can we just do as follows if we always avoid auto-commit?

Suggested change
if (originalAutoCommit) {
connection.setAutoCommit(false);
}
connection.setAutoCommit(false);

Copy link
Copy Markdown
Contributor

@Torch3333 Torch3333 left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

Comment on lines -55 to -56
execute(
connection, getDeleteTableMetadataStatement(namespace, table), requiresExplicitCommit);
Copy link
Copy Markdown
Collaborator

@brfrn169 brfrn169 Apr 8, 2026

Choose a reason for hiding this comment

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

requiresExplicitCommit is false except when using Oracle with the SERIALIZABLE isolation level. So this change handles the Oracle + SERIALIZABLE case, correct?

(Update) Sorry, I was wrong here. Please disregard this comment.,

@KodaiD
Copy link
Copy Markdown
Member Author

KodaiD commented Apr 13, 2026

@brfrn169 and I talked it over, and we've decided to look into a more radical refactor for this issue. We'll discuss this again post-v3.18 release. For now, I'll set this PR to Draft.

@KodaiD KodaiD marked this pull request as draft April 13, 2026 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants