Skip to content

fix: support MySQL user-level lock functions#24909

Merged
mergify[bot] merged 8 commits into
matrixorigin:4.0-devfrom
jiangxinmeng1:fix-user-level-lock-functions
Jun 16, 2026
Merged

fix: support MySQL user-level lock functions#24909
mergify[bot] merged 8 commits into
matrixorigin:4.0-devfrom
jiangxinmeng1:fix-user-level-lock-functions

Conversation

@jiangxinmeng1

@jiangxinmeng1 jiangxinmeng1 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) does this PR fix or relate to?

Fixes #24728

What this PR does / why we need it:

What

  • add GET_LOCK, RELEASE_LOCK, and IS_FREE_LOCK built-in functions
  • implement lightweight connection-owned named lock semantics for MySQL compatibility
  • cover lock acquire/release/free/null behavior in function tests

Why

Fixes #24728. Prisma Migrate calls GET_LOCK before applying migrations.

Tests

  • CGO_CFLAGS="-I/home/jiangxinmeng/workspace/matrixone-24728-lock-funcs/thirdparties/install/include" go test ./pkg/sql/plan/function

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@XuPeng-SH XuPeng-SH 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.

I found multiple blocking issues in the current implementation.

  1. The named-lock state is only a package-global in-memory map inside one CN process. In MatrixOne this means two sessions routed to different CNs can both acquire the same lock name at the same time, so the core exclusivity guarantee is broken for real cross-session coordination.

  2. Locks are never released when the owning session disconnects. The only mutations of the new lock map are explicit acquire/release calls, and this PR does not add any session-teardown cleanup path. So a client that exits without RELEASE_LOCK() can leave the lock stuck forever until the CN restarts, which is not compatible with MySQL named-lock semantics.

  3. GET_LOCK(name, timeout) handles timeout semantics incorrectly: timeout <= 0 returns 0 immediately, but MySQL compatibility requires timeout = 0 to mean no-wait and negative timeout to mean wait indefinitely (subject to session cancellation).

  4. The unhappy-path coverage is still thin around the new blocking behavior. There are no tests for disconnect cleanup, successful wait-then-acquire, timeout expiry, context cancellation while waiting, or the reentrant refcount path.

Because the first two are real behavior bugs and the third is a compatibility bug in the exposed SQL contract, I am requesting changes.

@jiangxinmeng1 jiangxinmeng1 force-pushed the fix-user-level-lock-functions branch from c6ab3b7 to 5ca0b17 Compare June 10, 2026 03:01
@jiangxinmeng1

Copy link
Copy Markdown
Contributor Author

Updated the PR to address the review request:

  • GET_LOCK now uses the CN lockservice instead of a package-local map, so different CNs coordinate through the existing distributed lock path.
  • Lock ownership is keyed by session id and lock name, with local refcounts only used for reentrant RELEASE_LOCK semantics.
  • Session.Close now calls ReleaseUserLevelLocks to clean up held named locks on disconnect.
  • Timeout behavior is updated: 0 uses FastFail/no-wait, positive values use context timeout, negative values wait indefinitely until session/query cancellation.
  • Added tests for cross-service contention via a shared LockService fake, wait-then-acquire, timeout expiry, context cancellation, reentrant refcount, and cleanup.

Tests run:

  • CGO_CFLAGS="-I/home/jiangxinmeng/workspace/matrixone-24728-lock-funcs/thirdparties/install/include" go test ./pkg/sql/plan/function
  • CGO_CFLAGS="-I/home/jiangxinmeng/workspace/matrixone-24728-lock-funcs/thirdparties/install/include" go test ./pkg/frontend -run TestNonExistent

@CLAassistant

CLAassistant commented Jun 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

…ock-functions

# Conflicts:
#	pkg/sql/plan/function/function_id.go
#	pkg/sql/plan/function/function_id_test.go

@XuPeng-SH XuPeng-SH 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.

Reviewed the latest fix approach, ignoring CI status. The implementation now addresses the earlier correctness issues around distributed locking, session cleanup, timeout semantics, RELEASE_LOCK NULL/0 semantics, empty/overlong names, multibyte length, and case-insensitive lock names. However, this PR introduces new public SQL functions (GET_LOCK, RELEASE_LOCK, IS_FREE_LOCK) for Prisma/MySQL compatibility and currently adds only Go unit tests; there is no BVT/end-to-end SQL case under test/distributed/cases. Please add at least one function BVT covering the SQL contract, e.g. GET_LOCK('prisma_migrate_lock', 0), IS_FREE_LOCK before/after acquire/release, RELEASE_LOCK for held and never-created locks, and NULL argument behavior. The fake-lockservice unit tests are strong, but they do not verify SQL parsing/planning/execution or result NULL/0/1 behavior through mo-tester.

@XuPeng-SH XuPeng-SH 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.

Re-reviewed the latest head with CI status ignored. The previous issues are addressed: the implementation uses the lockservice for cross-CN coordination, releases session-owned locks on Session.Close, handles timeout semantics, returns the correct RELEASE_LOCK 1/0/NULL states, normalizes names case-insensitively, validates empty/overlong/multibyte names, and preserves reentrant ownership. The new BVT now covers the public SQL path for GET_LOCK/RELEASE_LOCK/IS_FREE_LOCK, including NULL and never-created lock behavior. No blocking issue found in the fix approach.

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 adds MySQL-compatible user-level advisory lock built-ins (GET_LOCK, RELEASE_LOCK, IS_FREE_LOCK) so clients like Prisma Migrate can acquire a named lock before running migrations, backed by the existing lockservice and released on session close.

Changes:

  • Register new built-in functions and function IDs for get_lock, release_lock, and is_free_lock.
  • Implement connection-owned named lock semantics (acquire, release, free check, ref-counting, and session-close cleanup).
  • Add both BVT distributed SQL cases and Go unit tests covering core behaviors (acquire/release/free, contention, wait/timeout/cancel, NULL handling, length/case rules).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/distributed/cases/function/func_user_lock.test New distributed BVT case for user-level lock functions behavior.
test/distributed/cases/function/func_user_lock.result Expected outputs for the new BVT case.
pkg/sql/plan/function/list_builtIn.go Registers GET_LOCK / RELEASE_LOCK / IS_FREE_LOCK built-ins and their overloads.
pkg/sql/plan/function/function_test.go Adds a unit test to ensure the built-ins are registered as expected.
pkg/sql/plan/function/function_id.go Adds function IDs and name→ID registrations for the new functions.
pkg/sql/plan/function/function_id_test.go Updates function ID expectations to include the new IDs.
pkg/sql/plan/function/func_unary.go Implements lock acquisition/release/free-check and per-session cleanup logic.
pkg/sql/plan/function/func_unary_test.go Adds unit tests for lock behavior (contention, wait, timeout/cancel, refcount, name rules).
pkg/frontend/session.go Ensures user-level locks held by a session are released during session close.

Comment thread pkg/sql/plan/function/func_unary.go
Comment thread pkg/sql/plan/function/func_unary.go
Comment thread pkg/sql/plan/function/func_unary.go
…ock-functions

# Conflicts:
#	pkg/sql/plan/function/function_id_test.go
@jiangxinmeng1

Copy link
Copy Markdown
Contributor Author

@Mergifyio queue

@mergify

mergify Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-06-16 06:57 UTC · Rule: main
  • Checks skipped · PR is already up-to-date
  • Merged2026-06-16 06:57 UTC · at 5d0d37a1f2d07e4cc0e352d1a886933c49676e78 · squash

This pull request spent 22 seconds in the queue, including 4 seconds running CI.

Required conditions to merge
  • #approved-reviews-by >= 1 [🛡 GitHub branch protection]
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-decision = APPROVED [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-neutral = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-skipped = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / SCA Test on Ubuntu/x86
    • check-neutral = Matrixone CI / SCA Test on Ubuntu/x86
    • check-skipped = Matrixone CI / SCA Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-neutral = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-skipped = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Utils CI / Coverage
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86

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

Labels

kind/bug Something isn't working size/XL Denotes a PR that changes [1000, 1999] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants