postgres-locking-joins
Skill0 starsChanged 39 days agoMITView on GitHub
Use when PostgreSQL SELECT FOR UPDATE or FOR NO KEY UPDATE joins return missing rows or NULL related fields after lock waits, especially when concurrent transactions change a joined foreign key under Read Committed.
In this repository66 other files it gives its agents.
- AGENTS.mdAGENTS.md
- ai-bug-patternsSkill
- compressed-ndjson-boundariesSkill
- http-resume-integritySkill
- linux-io-latency-triageSkill
- macos-disk-space-recoverySkill
- minimal-sufficient-evidenceSkill
- modularize-large-filesSkill
- patch-reproducer-validitySkill
- prompt-cache-boundariesSkill
- proton-drive-selective-backupSkill
- transactional-outbox-deliverySkill
- conventional-commitsSkill
- git-advanced-mergingSkill
- git-bisect-forensicsSkill
- git-data-recoverySkill
- git-hooksSkill
- git-rerereSkill
- git-reset-mechanicsSkill
- git-revisions-syntaxSkill
- git-rewriting-historySkill
- git-submodulesSkill
- git-worktreesSkill
- github-ssh-keysSkill
- npm-publish-ci-pitfallsSkill
- sapling-stacked-pr-workflowSkill
- go-concurrency-patternsSkill
- go-data-idiomsSkill
- go-error-handlingSkill
- go-interfaces-embeddingSkill
- go-pprof-profilingSkill
- marketing-funnel-diagnosisSkill
- marketing-geo-experimentsSkill
- marketing-incrementalitySkill
- marketing-positioning-testsSkill
- python-descriptors-mroSkill
- python-logging-cookbookSkill
- python-scaling-regression-testsSkill
- python-unicode-gotchasSkill
- rust-compile-time-invariantsSkill
- rust-deterministic-concurrency-testsSkill
- rust-error-identity-boundariesSkill
- rust-regex-search-contractsSkill
- rust-runtime-bug-classesSkill
- rust-tokio-actor-deliverySkill
- rust-tokio-cancellation-safetySkill
- sales-discovery-qualificationSkill
- sales-mutual-action-plansSkill
- sales-pipeline-forecast-calibrationSkill
- sales-value-negotiationSkill
- ai-triage-evaluationSkill
- container-image-patchingSkill
- dependency-artifact-integritySkill
- dnssec-sentinel-diagnosticsSkill
- iam-policy-change-replaySkill
- rbvm-applicabilitySkill
- rbvm-asset-evidenceSkill
- rbvm-guarded-remediationSkill
- rbvm-priority-decisionsSkill
- rbvm-risk-exceptionsSkill
- The first 60 shown.
The file
Files
PostgreSQL Locking Joins
Row locking does not refresh the statement snapshot or restart the statement from scratch. Under Read Committed, rechecking an updated base row against previously fetched join data can discard a match despite a valid foreign key.
Diagnose before changing isolation
Capture SQL, isolation, server version, and EXPLAIN. Look for LockRows above a join and concurrent join-key updates. Reproduction harness: A updates; B starts its locking join; verify B is blocked before committing A. Use only an explicitly selected disposable database.
| Choice | Boundary |
| Split base-row lock and related read | Second statement gets a fresh Read Committed snapshot |
| Lock inside a CTE/subquery | Inspect the plan; still one statement snapshot |
| Repeatable Read / Serializable | Both can raise 40001; only Serializable prevents serialization anomalies |
Lock first, then read
For work_item(id PRIMARY KEY, queue_id NOT NULL REFERENCES queue(id)), run as a non-interactive psql script:
\set ON_ERROR_STOP on
\unset locked_queue_id
BEGIN ISOLATION LEVEL READ COMMITTED;
SELECT queue_id AS locked_queue_id
FROM work_item WHERE id = 42
FOR NO KEY UPDATE
\gset
SELECT * FROM queue WHERE id = :'locked_queue_id';
-- Validate and perform dependent writes here.
ROLLBACK; -- Demonstration only.Bind the returned key into the second statement. Abort/rollback on missing rows, including concurrent deletions. Keep dependent writes inside this transaction.
Sources: Haki Benita, 2026-02-24; PostgreSQL 18 isolation, locking, SELECT, retries, psql. Reviewed 2026-10-07; PostgreSQL 17.11 startup blocked by Unix-socket permissions; examples unexecuted. Recheck on the deployed version.
Pitfalls
- Locking the old related row as well does not repair the join; a left join can merely expose NULLs.
- A locking CTE cannot see a related row inserted after its statement snapshot; prefer separate statements when that race matters.
- Autocommit releases the first lock before the second read.
SKIP LOCKEDintentionally omits rows; it is not a correctness repair. - Base locks neither freeze related attributes nor protect absent rows. Broader invariants need a locking protocol followed by every relevant writer; acquire locks consistently.
- For
40001serialization failures or40P01deadlocks, retry the whole transaction, including decisions; avoid duplicating external side effects.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

