Skip to content

txn: Add test for the issue that transaction using fair locking multiple times in the first statement may make keeping-alive fail - #67141

Merged
ti-chi-bot[bot] merged 1 commit into
pingcap:masterfrom
MyonKeminta:m/fix-and-test-issue-66571
Mar 23, 2026
Merged

ti-chi-bot[bot] merged 1 commit into
pingcap:masterfrom
MyonKeminta:m/fix-and-test-issue-66571

Conversation

@MyonKeminta

@MyonKeminta MyonKeminta commented Mar 19, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #66571

Problem Summary:

This PR adds test for the issue #66571 .
It includes updating client-go, but was already included by other PRs.

What changed and how does it work?

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

Fix the issue that transaction using fair locking multiple times in the first statement may make keeping-alive fail, casuing unable to block other transactions or unexpected commit failure.

Summary by CodeRabbit

  • Tests
    • Expanded test coverage for pessimistic transaction fair locking behavior, validating lock timeout handling and concurrent transaction scenarios to enhance reliability.

Signed-off-by: MyonKeminta <MyonKeminta@users.noreply.github.com>
@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/needs-tests-checked labels Mar 19, 2026
@pantheon-ai

pantheon-ai Bot commented Mar 19, 2026 •

Copy link
Copy Markdown

Review Complete

Findings: 1 issues
Posted: 1
Duplicates/Skipped: 0

ℹ️ Learn more details on Pantheon AI.

@ti-chi-bot ti-chi-bot Bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed do-not-merge/needs-tests-checked labels Mar 19, 2026
@tiprow

tiprow Bot commented Mar 19, 2026

Copy link
Copy Markdown

Hi @MyonKeminta. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@coderabbitai

coderabbitai Bot commented Mar 19, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Added a new test function TestIssue66571 to validate pessimistic transaction fair locking behavior. The test exercises three scenarios using configurable parameters, setting lock TTL constraints and verifying that lock wait timeouts are properly enforced when multiple concurrent transactions contend for locks on the same resources.

Changes

Cohort / File(s) Summary
New Test Addition
tests/realtikvtest/pessimistictest/pessimistic_test.go
Added TestIssue66571 to test pessimistic transaction fair locking behavior across three scenarios with different lock contention patterns and timeout validation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

sig/transaction, size/M, ok-to-test

Suggested reviewers

  • lcwangchao
  • zyguan
  • ekexium

Poem

🐰 A lock test hops into the fray,
Fair locking dances in TiDB's way,
Three scenarios tested with care,
Timeouts enforced, locks held fair! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the test addition for issue #66571 regarding fair locking and keeping-alive failures in pessimistic transactions.
Linked Issues check ✅ Passed The test TestIssue66571 comprehensively exercises the fair locking scenario from issue #66571 with multiple lock contention scenarios and timeout assertions.
Out of Scope Changes check ✅ Passed The changes are strictly limited to adding a test function for issue #66571 with no unrelated modifications.
Description check ✅ Passed The PR description follows the template with Issue Number correctly linked (#66571), identifies the change as a test addition, includes a checklist with Unit test selected, and provides a release note.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes with custom instructions.

Set the reviews.auto_title_instructions setting to generate a title for your PR based on the changes in the PR with custom instructions.

@hawkingrei

Copy link
Copy Markdown
Contributor

/ok-to-test

@ti-chi-bot ti-chi-bot Bot added the ok-to-test Indicates a PR is ready to be tested. label Mar 19, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/realtikvtest/pessimistictest/pessimistic_test.go (1)

3503-3561: Name the scenarios instead of passing booleans.

test(true, false) and test(true, true) make the matrix hard to read, and when one branch fails the output will not say which scenario regressed. A small table-driven setup with name plus t.Run would make the retry/primary-change cases much easier to understand and debug.

As per coding guidelines, Code SHOULD be self-documenting through clear naming and structure; when naming alone may not make intent obvious, add a brief comment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/realtikvtest/pessimistictest/pessimistic_test.go` around lines 3503 -
3561, The anonymous test closure taking (isRetried bool, isPrimaryChanged bool)
makes outcomes opaque; refactor into a table-driven subtests using t.Run with
descriptive names (e.g., "no-retry", "retry-no-primary-change",
"retry-primary-changed") and a struct with fields Retried and PrimaryChanged,
then iterate the table and call the existing test body (the logic inside the
test closure) per entry; update references to isRetried/isPrimaryChanged inside
the closure (or convert the closure to a helper func like runPessimisticTest) to
use the struct fields, so failures print the subtest name and intent clearly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/realtikvtest/pessimistictest/pessimistic_test.go`:
- Around line 3507-3556: The test only exercises fair-locking via UPDATE but
misses the unique-key point-get regression path (SELECT ... FOR UPDATE) reported
in `#66571`; add a variant where session tk does a "SELECT ... FOR UPDATE" on uk =
10 as its first statement (using tk.MustQuery or tk.MustExec with "select * from
t where uk = 10 for update") before the conflicting operations, keeping the rest
of the flow (tk2 waits with update and hits ErrLockWaitTimeout, tk commits,
final check) and reuse the existing variables (additionalInitStmt,
earlyConflictingStmt, expectedFinalData) and session names (tk, tk2, tk3) so the
new branch follows the same setup/teardown and assertions as the other cases.

---

Nitpick comments:
In `@tests/realtikvtest/pessimistictest/pessimistic_test.go`:
- Around line 3503-3561: The anonymous test closure taking (isRetried bool,
isPrimaryChanged bool) makes outcomes opaque; refactor into a table-driven
subtests using t.Run with descriptive names (e.g., "no-retry",
"retry-no-primary-change", "retry-primary-changed") and a struct with fields
Retried and PrimaryChanged, then iterate the table and call the existing test
body (the logic inside the test closure) per entry; update references to
isRetried/isPrimaryChanged inside the closure (or convert the closure to a
helper func like runPessimisticTest) to use the struct fields, so failures print
the subtest name and intent clearly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3fa04150-3f55-47af-be6c-ba3a36e01a6f

📥 Commits

Reviewing files that changed from the base of the PR and between b52c9b8 and 1dc91ef.

📒 Files selected for processing (1)
  • tests/realtikvtest/pessimistictest/pessimistic_test.go

Comment on lines +3507 to +3556
additionalInitStmt := ""
earlyConflictingStmt := ""
testedStmt := "update t set v = v + 1 where uk = 10"
expectedFinalData := []string{"1 10 101"}

if isRetried {
if !isPrimaryChanged {
additionalInitStmt = "insert into t values (0, 0, 10)"
earlyConflictingStmt = "update t set v = 200 where uk = 10"
expectedFinalData = []string{"0 0 10", "1 10 201"}
} else {
additionalInitStmt = "insert into t values (0, 0, 9)"
earlyConflictingStmt = "update t set v = 10 where id = 0"
testedStmt = `
with
x as (select /*+ MERGE() */ * from t where id = 0)
update x join t on x.v = t.uk set t.v = t.v + 1 where t.uk = 10`
expectedFinalData = []string{"0 0 10", "1 10 101"}
}
}

defer setLockTTL(100).restore()
tk.MustExec("set @@tidb_pessimistic_txn_fair_locking=1")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id int primary key, uk int unique, v int)")
if additionalInitStmt != "" {
tk.MustExec(additionalInitStmt)
}
tk.MustExec("insert into t values (1, 10, 100)")
tk2.MustExec("use test")
tk2.MustExec("set innodb_lock_wait_timeout = 1")

tk.MustExec("begin pessimistic")
if earlyConflictingStmt != "" {
tk3 := testkit.NewTestKit(t, store)
tk3.MustExec("use test")
tk3.MustExec(earlyConflictingStmt)
}
tk.MustExec(testedStmt)

tk2.MustExec("begin pessimistic")
err := tk2.ExecToErr("update t set v = v + 2 where uk = 10")
require.Error(t, err)
require.ErrorIs(t, err, storeerr.ErrLockWaitTimeout)
tk2.MustExec("commit")

tk.MustExec("commit")

tk.MustQuery("select * from t").Check(testkit.Rows(expectedFinalData...))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Please cover the original SELECT ... FOR UPDATE regression path directly.

All three variants exercise fair-locking through UPDATE, but #66571 is a unique-key point-get SELECT ... FOR UPDATE case. This file already treats pessimisticSelectForUpdateRetry and pessimisticDMLRetry as distinct paths, so a DML-only regression test can stay green while the reported FOR UPDATE behavior breaks again. Please add a case where session 1’s first statement is SELECT ... FOR UPDATE on uk = 10, and session 2 waits on the same key.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/realtikvtest/pessimistictest/pessimistic_test.go` around lines 3507 -
3556, The test only exercises fair-locking via UPDATE but misses the unique-key
point-get regression path (SELECT ... FOR UPDATE) reported in `#66571`; add a
variant where session tk does a "SELECT ... FOR UPDATE" on uk = 10 as its first
statement (using tk.MustQuery or tk.MustExec with "select * from t where uk = 10
for update") before the conflicting operations, keeping the rest of the flow
(tk2 waits with update and hits ErrLockWaitTimeout, tk commits, final check) and
reuse the existing variables (additionalInitStmt, earlyConflictingStmt,
expectedFinalData) and session names (tk, tk2, tk3) so the new branch follows
the same setup/teardown and assertions as the other cases.

@codecov

codecov Bot commented Mar 19, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.8920%. Comparing base (b52c9b8) to head (1dc91ef).
⚠️ Report is 20 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #67141        +/-   ##
================================================
+ Coverage   77.7082%   77.8920%   +0.1837%     
================================================
  Files          2016       1942        -74     
  Lines        552461     548707      -3754     
================================================
- Hits         429308     427399      -1909     
+ Misses       121411     121296       -115     
+ Partials       1742         12      -1730     
Flag Coverage Δ
integration 41.5294% <ø> (-6.5933%) ⬇️
unit 77.0563% <ø> (+0.8271%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 63.6984% <ø> (+6.6885%) ⬆️
parser ∅ <ø> (∅)
br 49.4898% <ø> (-11.3627%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

}
}

defer setLockTTL(100).restore()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[P2] Test flakiness risk from very short lock TTL (100ms) in realtikv test

Why: May intermittently fail in CI because keeping locks alive for a 1s wait requires frequent TTL heartbeats; small scheduling/RPC jitter can let locks expire and make the waiter acquire the lock instead of timing out.

Evidence: defer setLockTTL(100).restore() with tk2.MustExec("set innodb_lock_wait_timeout = 1") and require.ErrorIs(t, err, storeerr.ErrLockWaitTimeout) at tests/realtikvtest/pessimistictest/pessimistic_test.go:3528. The keepalive ticker period is ManagedLockTTL/2 (~50ms), and any transient scheduling/RPC stall can let the lock appear expired.

@ti-chi-bot ti-chi-bot Bot added approved needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Mar 19, 2026
@ekexium

ekexium commented Mar 23, 2026

Copy link
Copy Markdown
Member

/retest

@ti-chi-bot

ti-chi-bot Bot commented Mar 23, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cfzjywxk, ekexium

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Mar 23, 2026
@ti-chi-bot

ti-chi-bot Bot commented Mar 23, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-03-19 06:54:38.355247633 +0000 UTC m=+426405.442905160: ☑️ agreed by cfzjywxk.
  • 2026-03-23 08:39:31.550526307 +0000 UTC m=+171167.586596567: ☑️ agreed by ekexium.

@MyonKeminta MyonKeminta added the needs-cherry-pick-release-8.5 Should cherry pick this PR to release-8.5 branch. label Mar 23, 2026
@ti-chi-bot
ti-chi-bot Bot merged commit 8c83d3f into pingcap:master Mar 23, 2026
35 checks passed
@ti-chi-bot

Copy link
Copy Markdown
Member

In response to a cherrypick label: new pull request created to branch release-8.5: #67234.

@MyonKeminta
MyonKeminta deleted the m/fix-and-test-issue-66571 branch March 23, 2026 11:09
ti-chi-bot Bot pushed a commit that referenced this pull request Mar 24, 2026
…ng multiple times in the first statement may make keeping-alive fail (#67141) (#67234)

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

Labels

approved lgtm needs-cherry-pick-release-8.5 Should cherry pick this PR to release-8.5 branch. ok-to-test Indicates a PR is ready to be tested. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unexpected lock behavior for point get FOR UPDATE read on unique key

5 participants