Concurrency
6 / 11 · connections and snapshots in the full document · PDF
A load runs on whatever it is given. On a connection or a transaction, every query runs in turn and sees the transaction's own uncommitted writes. On a Pooled pool, the queries of each level run at the same time, each on a pooled connection held for that query only — and on PostgreSQL, all of them can share one snapshot, so the levels of a load see the same database even while others write.
The caller's connection. Wherever a load or write takes a connection, it accepts a connection, a sqlx::Transaction, a pooled connection or a Pooled pool, and every query of a load runs on the connection given, so it sees the uncommitted writes of its transaction MPA-DB-5. That is the default because it is the one that is always correct. Queries are not pipelined on one connection MPA-NOT-8: SQLx 0.9 has no pipelining API.
A pool, level by level. With a Pooled pool the child queries of each level run together, each on a connection held for that query only, so a load uses at most the connections of its Pooled and cannot deadlock on its own pool MPA-LOAD-11. The keys of a level are collected from the rows above before its queries start. Pooled::snapshot begins REPEATABLE READ READ ONLY on one connection, exports its snapshot, and imports it on the others; it exists only for PostgreSQL, so asking for it on MySQL or SQLite does not compile.
Joining up front. Every connection imports the snapshot before the first query runs. If a query failed while others were still joining, its transaction could end under them; joining first removes that race. Pooled::read_committed works on any database and lets each query see what is committed when it runs. Graph loads run their queries one at a time on one connection, because which query reaches an entity first decides where its row comes from, and that should not vary from run to run.