support/db: Support concurrent queries in a transaction #1838
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
PR Checklist
PR Structure
otherwise).
services/friendbot
, orall
ordoc
if the changes are broad or impact manypackages.
Thoroughness
.md
files, etc... affected by this change). Take a look in the
docs
folder for a given service,like this one.
Release planning
needed with deprecations, added features, breaking changes, and DB schema changes.
semver, or if it's mainly a patch change. The PR is targeted at the next
release branch if it's not a patch change.
Summary
support/db.Session
did not support concurrent Exec/Query queries sent in a DB transaction. This commit adds support for this.Close #1836
Goal and scope
Postgres protocol does not allow sending Exec query results from previously sent Query haven't been fully read. This issue manifested itself when a PR that's sending read and write queries in multiple goroutines was merged.
To fix this a new
wrMutex
was created and added toSession
.wrMutex
works exactly likesync.RWMutex
except lock can be held by an arbitrary number of writers (readers insync.RWMutex
) or a single reader (writer insync.RWMutex
). InSession
, before each query we check if it's sent in a transaction and, if so, we callexecLock
forExec
calls andqueryLock
forGet
andSelect
calls. This way, only a singleGet
/Select
can be executed at any given time but multipleExec
will work concurrently. This shouldn't affect queries that run outside a DB transaction.More info: lib/pq#81 lib/pq#635
Why was it working before?
It was working before because there was no code running both read and write queries concurrently:
Known limitations & issues
I confirmed it fixes #1836 but it changes the criticial code used by multiple apps. We should test it extensively before merging.