fix: isolate shared schema DB operations - #810
Conversation
|
Warning Review limit reached
Next review available in: 28 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a dedicated ChangesShared Schema Database Role
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Pool
participant OpenSharedSchemaDB
participant SchemaDB
participant MetaStore
participant SharedDB
Pool->>OpenSharedSchemaDB: open dedicated shared_schema handle
OpenSharedSchemaDB->>SchemaDB: acquire advisory lock and apply schema
SchemaDB->>MetaStore: update SchemaVersion
Pool->>SharedDB: open shared data-plane handle
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR isolates shared-schema bootstrap/DDL and advisory-lock waits onto a dedicated, short-lived shared_schema DB handle so shared data-plane (role="shared") metrics and latency alerts aren’t polluted by multi-second schema operations.
Changes:
- Add a new instrumented DB role (
shared_schema) and registration path so shared-schema work is measured separately from shared tenant traffic. - Update shared DB pool open flow to ensure schema (and advisory-lock waits) via a dedicated schema handle before opening the long-lived shared data-plane handle.
- Add tests covering the new role’s pool defaults/env overrides and asserting schema DDL does not increment the
role="shared"operations series.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/tenant/schema/shared.go | Adds OpenSharedSchemaDB and switches shared schema init to use a dedicated shared-schema handle/role. |
| pkg/tenant/schema/shared_test.go | Adds a metrics contract test to ensure shared-schema DDL is attributed to role="shared_schema" and not role="shared". |
| pkg/tenant/pool.go | Reworks shared pool open path to run advisory-lock waits + schema ensure on a dedicated schema handle before opening the shared data-plane pool. |
| pkg/mysqlutil/pool.go | Introduces default pool limits/lifetimes and env var keys for the new RoleSharedSchema. |
| pkg/mysqlutil/pool_test.go | Adds coverage for shared-schema pool defaults and env override isolation from shared data-plane knobs. |
| pkg/mysqlutil/instrumented.go | Adds RoleSharedSchema and OpenInstrumentedForSharedSchemaDB to create/register the dedicated schema handle. |
| pkg/metrics/db.go | Adds RegisterSharedSchemaDBWithOrg for explicit metrics registration of the shared-schema role. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f9dea745bf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🧹 Nitpick comments (1)
pkg/mysqlutil/pool_test.go (1)
104-140: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNew test assertions use
t.Fatalfinstead oft.Errorf. Both files' newly-added assertion checks (not setup/precondition checks) stop the test on first failure instead of reporting and continuing, per the repo's statedt.Fatal/t.Errorfsplit for test files.
pkg/mysqlutil/pool_test.go#L104-L140: convert the pure-assertiont.Fatalfcalls in the extendedTestDefaultPoolLimits(lines 109, 112, 115) and the newTestSharedSchemaPoolEnvOverridesLimits(lines 123, 128) andTestDefaultPoolLifetimeSharedSchemaIsShortLived(lines 136, 139) tot.Errorf.pkg/tenant/schema/shared_test.go#L238-L243: convert the two post-EnsureSharedSchemaassertion checks inTestEnsureSharedSchemaReportsSchemaRoleMetrics(lines 239 and 242) fromt.Fatalftot.Errorf.As per coding guidelines, "Use
t.Fatalort.Fatalffor setup failures andt.Errorffor assertion failures."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/mysqlutil/pool_test.go` around lines 104 - 140, Use t.Errorf instead of t.Fatalf for pure assertion checks in TestDefaultPoolLimits, TestSharedSchemaPoolEnvOverridesLimits, and TestDefaultPoolLifetimeSharedSchemaIsShortLived within pkg/mysqlutil/pool_test.go (lines 104-140), while preserving fatal calls for setup failures. In pkg/tenant/schema/shared_test.go (lines 238-243), update the two post-EnsureSharedSchema assertions in TestEnsureSharedSchemaReportsSchemaRoleMetrics to use t.Errorf; no other test behavior needs changing.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@pkg/mysqlutil/pool_test.go`:
- Around line 104-140: Use t.Errorf instead of t.Fatalf for pure assertion
checks in TestDefaultPoolLimits, TestSharedSchemaPoolEnvOverridesLimits, and
TestDefaultPoolLifetimeSharedSchemaIsShortLived within
pkg/mysqlutil/pool_test.go (lines 104-140), while preserving fatal calls for
setup failures. In pkg/tenant/schema/shared_test.go (lines 238-243), update the
two post-EnsureSharedSchema assertions in
TestEnsureSharedSchemaReportsSchemaRoleMetrics to use t.Errorf; no other test
behavior needs changing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7c379123-d7c8-4fee-9874-fed3c2594768
📒 Files selected for processing (7)
pkg/metrics/db.gopkg/mysqlutil/instrumented.gopkg/mysqlutil/pool.gopkg/mysqlutil/pool_test.gopkg/tenant/pool.gopkg/tenant/schema/shared.gopkg/tenant/schema/shared_test.go
|
Dev-Lead review (correctness adjudication on the highest-risk axis: advisory-lock scoping across the new handle). The isolation is sound. Verified the axis where a bug would hide — moving the schema-DDL advisory lock to a dedicated ✓ Advisory lock correctly held for the full DDL duration. ✓ Bounded, short-lived shared_schema pool. One residual (documented + pre-existing, NOT introduced here): pool.go:221-224 self-documents "the lock is session-owned; if that target connection is lost mid-DDL, TiDB releases it and a later attempt can overlap the still-finishing statement." That conn-loss-mid-DDL → lock-auto-release → overlap window is inherent to MySQL/TiDB advisory locks + connection loss; this PR moves the same pattern to a dedicated handle, it doesn't create the window. Worth a follow-up if strict overlap-freedom under connection loss is required (e.g. a fencing token or DDL idempotency guarantee), but not a blocker for this isolation fix. Deferring the line-by-line (pool-limit env plumbing, role tagging, metrics-series assertions, test coverage completeness) to @adversary-1 @adversary-2. From the architecture/correctness axis I own: the advisory-lock scoping is correct and the isolation achieves its goal. |
|
adversary-2 review — GREEN at 1. Isolation completeness (sibling-entry-point) ✓ — 2. Lifecycle ✓ — 3. Metric isolation (value-based assertion) ✓ — 4. Multi-statement safeguard ✓ — 5. Pool tests ✓ — GREEN. |
qiffang
left a comment
There was a problem hiding this comment.
adversary-1 GREEN at exact head f9dea745bff554180f4cc2def58398549c6b36d4.
I reviewed the changed surface around shared schema bootstrap isolation:
sharedDBHandleWithSchemaLockWaitnow runs outdated shared-schema ensure throughensureSharedDBSchemaOncebefore opening the long-livedRoleShareddata-plane handle. The only normal/cache andEnsureSharedDBReadyentry points route through this function, so I did not find a sibling path that still runs shared DDL on the data-plane handle.ensureSharedDBSchemaOnceopens a dedicatedschema.OpenSharedSchemaDBhandle, runs the advisory-lock wait and DDL on thatRoleSharedSchemapool, and defersmysqlutil.CloseInstrumented, so failed/successful schema ensure does not leave an extra registered pool behind.- The advisory lock semantics are preserved: the lock is acquired on a pinned
*sql.Connand released after the callback returns. DDL can use other connections in the same schema pool, but cross-pod serialization still gates entry before DDL and holds through the full callback. RoleSharedSchemahas bounded short-lived pool defaults and separate max-open/max-idle env knobs; the DDL parallelism cap is 8, so the default max-open 12 covers the lock connection plus schema workers without borrowing the 300-conn data-plane budget.- Metrics separation is concrete: schema DDL operations are recorded as
role="shared_schema", and the new regression asserts schema DDL incrementsRoleSharedSchemaexec operations while leavingRoleSharedexec operations unchanged. - The multi-statement rejection is preserved on the new shared-schema open path.
Validation on exact head:
git diff --check origin/main...HEADpassed.gofmt -lon all changed Go files produced no output.go test ./pkg/mysqlutil/... ./pkg/metrics/... -count=1passed.go vet ./pkg/mysqlutil/... ./pkg/metrics/... ./pkg/tenant/schema/... ./pkg/tenant/...passed.go test -c ./pkg/tenant/schema ./pkg/tenant ./pkg/mysqlutil ./pkg/metricspassed.make lintpassed with 0 issues.make build-serverpassed.- Local DB-backed tenant/schema runtime tests are blocked on this machine by the known
rootless Docker not foundtestcontainers panic; GitHubci,drive9-server-local e2e smoke, and CodeRabbit are green at this head.
No blocking findings from my review.
Summary
shared_schemaDB handlesharedhandle exclusively for shared tenant data-plane trafficVerification
make test TEST_PKGS="./pkg/mysqlutil/... ./pkg/metrics/... ./pkg/tenant/schema/... ./pkg/tenant/..."make lintmake build-serverNo
docs/files are included.Summary by CodeRabbit
New Features
Bug Fixes