Skip to content

[#12453] improvement(core): add OCC for schema writes - #12456

Draft
yuqi1129 wants to merge 3 commits into
apache:mainfrom
yuqi1129:feat/12342-occ-schema
Draft

[#12453] improvement(core): add OCC for schema writes#12456
yuqi1129 wants to merge 3 commits into
apache:mainfrom
yuqi1129:feat/12342-occ-schema

Conversation

@yuqi1129

@yuqi1129 yuqi1129 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Add database-backed optimistic concurrency control and transaction boundaries for schema writes.

  • Advance the schema OCC version on every alter, and guard alter and drop with a compare-and-set on the observed version, classifying a failed CAS as either a stale-version conflict or an already-missing entity.
  • Make managed schema creation insert-only, and take a shared lock on the parent catalog row, so a concurrent same-name create cannot overwrite the winner and a schema cannot be created below a catalog that is being dropped.
  • Serialize hierarchical ancestor materialization and schema drops through the catalog row so overlapping cascades share one lock order.
  • Lock the parent schema row before writing a table, view, fileset, function, model, or topic.
  • Check views and functions before a non-cascade schema drop.

Accepted tradeoff: a hierarchical schema create that materializes implicit ancestors takes an exclusive lock on the catalog row, so every other schema create under that catalog waits until that transaction ends, even when it touches a different ancestor path. The exclusive lock is needed because two concurrent creates can both find the same ancestor missing and both insert it, and a shared lock does not prevent that under MySQL REPEATABLE READ. Catalogs with heavy concurrent hierarchical schema creation will therefore serialize on this lock. If it becomes a bottleneck, a narrower fence — locking only the ancestor rows being created and relying on the unique constraint plus a retry — can be done in a follow-up.

Rebased on current main (on top of #12374). Third of three PRs replacing #12350. Stacked on the catalog PR; review the top commit only. This PR also restores the two cross-entity TestMetalakeMetaService tests that could not pass before schema writes took the catalog row lock.

Why are the changes needed?

Managed schema operations previously consisted of multiple independent reads and writes. Concurrent alter, create, and drop requests could overwrite newer metadata, create children below a deleted parent, leave view and function rows orphaned, or run partial cascade cleanup. Overlapping hierarchical schema drops could also acquire descendant row locks in different orders.

Fix: #12453

Does this PR introduce any user-facing change?

Concurrent schema version conflicts are reported as HTTP 409. If the observed entity was deleted or renamed away, alter reports not found and drop preserves its idempotent false result. A managed schema create that loses a concurrent same-name create returns SchemaAlreadyExistsException instead of overwriting the winner.

How was this patch tested?

  • ./gradlew :core:test :core:javadoc :catalogs:catalog-fileset:test :catalogs:catalog-kafka:test -PskipITs (H2)
  • New and extended tests in TestSchemaMetaService, TestMetalakeMetaService, TestFilesetCatalogOperations, TestKafkaCatalogOperations.
  • MySQL and PostgreSQL coverage is left to CI (-PskipDockerTests=false).

Advance the metalake OCC version on every alter and guard alter and
delete with a compare-and-set on the observed version, classifying a
failed CAS as either a stale conflict or a missing entity.

Keep the metalake root CAS and the non-empty check or the cascade
cleanup inside one database transaction. A cascade locks the catalog
rows first, then compare-and-set deletes descendant catalogs and schemas
with their observed identifier-and-version pairs, so a concurrent child
write is reported instead of silently dropped.

Also add the shared OptimisticLockException factories used by the
follow-up catalog and schema changes.
Advance the catalog OCC version on every alter and guard alter and
delete with a compare-and-set on the observed version, classifying a
failed CAS as either a stale conflict or a missing entity.

Protect catalog creation with a shared lock on the parent metalake row
on MySQL and PostgreSQL, without changing the parent version, so a
catalog can no longer be created below a metalake that is being
dropped. H2 uses an exclusive lock because it has no shared row-lock
syntax.

Keep the catalog CAS and the non-empty check or the cascade cleanup
inside one database transaction, and CAS-delete descendant schemas with
their observed identifier-and-version pairs.
Advance the schema OCC version on every alter and guard alter and drop
with a compare-and-set on the observed version, classifying a failed
CAS as either a stale conflict or a missing entity.

Make managed schema creation insert-only so a concurrent same-name
create returns SchemaAlreadyExistsException instead of overwriting the
winner, and take a shared lock on the parent catalog row so a schema
cannot be created below a catalog that is being dropped. Serialize
hierarchical ancestor materialization and schema drops through the
catalog row so overlapping cascades share one lock order.

Lock the parent schema row before writing a table, view, fileset,
function, model, or topic, and check views and functions before a
non-cascade schema drop.

Accepted tradeoff: a hierarchical schema create that materializes
implicit ancestors takes an exclusive lock on the catalog row, because
two concurrent creates can both find the same ancestor missing and both
insert it, and a shared lock does not prevent that under MySQL
REPEATABLE READ.
@github-actions

Copy link
Copy Markdown

Code Coverage Report

Overall Project 68.71% +0.52% 🟢
Files changed 82.48% 🟢

Module Coverage
aliyun 1.72% 🔴
api 49.31% 🟢
authorization-common 85.96% 🟢
aws 42.04% 🟢
azure 2.47% 🔴
catalog-common 9.92% 🔴
catalog-fileset 79.77% 🟢
catalog-glue 68.95% 🟢
catalog-hive 79.4% 🟢
catalog-jdbc-common 45.7% 🟢
catalog-jdbc-doris 81.8% 🟢
catalog-jdbc-mysql 79.33% 🟢
catalog-jdbc-postgresql 83.39% 🟢
catalog-jdbc-starrocks 79.16% 🟢
catalog-kafka 76.72% 🟢
catalog-lakehouse-generic 59.18% 🟢
catalog-lakehouse-hudi 79.1% 🟢
catalog-lakehouse-iceberg 85.86% 🟢
catalog-lakehouse-paimon 84.23% 🟢
catalog-model 77.72% 🟢
cli 44.48% 🟢
client-java 78.46% 🟢
common 52.75% 🟢
core 83.63% -0.15% 🟢
filesystem-hadoop3 77.28% 🟢
flink 0.0% 🔴
flink-common 48.68% 🟢
flink-runtime 0.0% 🔴
gcp 14.12% 🔴
hadoop-auth 68.0% 🟢
hadoop-common 12.7% 🔴
hive-metastore-common 53.4% 🟢
iceberg-aliyun-bundle 0.0% 🔴
iceberg-common 64.75% 🟢
iceberg-rest-server 75.1% 🟢
idp-basic 86.02% 🟢
integration-test-common 0.0% 🔴
jobs 62.92% 🟢
lance-common 31.75% 🔴
lance-rest-server 63.47% 🟢
lineage 53.02% 🟢
optimizer 83.24% 🟢
optimizer-api 21.95% 🔴
server 87.38% 🟢
server-common 79.41% 🟢
spark 28.57% 🔴
spark-common 45.89% 🟢
tencent 69.84% 🟢
trino-connector 40.29% 🟢
Files
Module File Coverage
core MetalakeMetaSQLProviderFactory.java 100.0% 🟢
MetalakeMetaBaseSQLProvider.java 100.0% 🟢
FunctionMetaService.java 100.0% 🟢
TableMetaService.java 100.0% 🟢
ViewMetaService.java 100.0% 🟢
MetalakeMetaService.java 99.32% 🟢
SchemaMetaService.java 97.59% 🟢
CatalogMetaService.java 94.35% 🟢
FilesetMetaService.java 91.53% 🟢
CatalogMetaSQLProviderFactory.java 90.32% 🟢
CatalogMetaBaseSQLProvider.java 90.0% 🟢
ExceptionUtils.java 88.89% 🟢
POConverters.java 88.31% 🟢
CatalogMetaPostgreSQLProvider.java 85.71% 🟢
MetalakeMetaPostgreSQLProvider.java 83.33% 🟢
ModelMetaService.java 76.72% 🟢
SchemaMetaSQLProviderFactory.java 75.0% 🟢
TopicMetaService.java 72.48% 🟢
CatalogManager.java 70.56% 🟢
SchemaMetaBaseSQLProvider.java 68.0% 🟢
SchemaMetaPostgreSQLProvider.java 66.67% 🟢
MetalakeManager.java 65.88% 🟢
ManagedSchemaOperations.java 29.2% 🔴
CatalogMetaMapper.java 0.0% 🔴
MetalakeMetaMapper.java 0.0% 🔴
SchemaMetaMapper.java 0.0% 🔴

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Subtask] Add version-CAS OCC for schema writes

1 participant