@@ -68,6 +68,24 @@ use crate::{
6868 types:: HeightIndexed ,
6969} ;
7070
71+ /// When set to `true`, read transactions begin with
72+ /// `SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY` (no `DEFERRABLE`),
73+ /// so they start immediately instead of waiting for a safe serializable snapshot.
74+ #[ cfg( not( feature = "embedded-db" ) ) ]
75+ static NO_DEFERRABLE_ON_READ : std:: sync:: atomic:: AtomicBool =
76+ std:: sync:: atomic:: AtomicBool :: new ( false ) ;
77+
78+ /// Configure whether read transactions on Postgres should omit `DEFERRABLE`.
79+ ///
80+ /// When `true`, `Read::begin` issues `SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY`
81+ /// (no `DEFERRABLE`) so the transaction starts immediately rather than waiting for a safe
82+ /// serializable snapshot. Default: `false`. Call this once at startup based on the operator's
83+ /// chosen configuration.
84+ #[ cfg( not( feature = "embedded-db" ) ) ]
85+ pub fn set_no_deferrable_on_read ( value : bool ) {
86+ NO_DEFERRABLE_ON_READ . store ( value, std:: sync:: atomic:: Ordering :: Relaxed ) ;
87+ }
88+
7189pub type Query < ' q > = sqlx:: query:: Query < ' q , Db , <Db as Database >:: Arguments < ' q > > ;
7290pub type QueryAs < ' q , T > = sqlx:: query:: QueryAs < ' q , Db , T , <Db as Database >:: Arguments < ' q > > ;
7391
@@ -186,12 +204,23 @@ impl TransactionMode for Read {
186204 // (SERIALIZABLE), and we want to wait until this is possible rather than failing
187205 // (DEFERRABLE).
188206 //
207+ // Setting `ESPRESSO_NODE_POSTGRES_NO_DEFERRABLE=true` disables the DEFERRABLE
208+ // option, so that read transactions start immediately and may instead fail with a
209+ // serialization error if they conflict with a concurrent write. This trades start-up
210+ // latency for the chance of a retry, and is opt-in.
211+ //
189212 // With SQLite, there is nothing to be done here, as SQLite automatically starts
190213 // transactions in read-only mode, and always has serializable concurrency unless we
191214 // explicitly opt in to dirty reads with a pragma.
192215 #[ cfg( not( feature = "embedded-db" ) ) ]
193- conn. execute ( "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE" )
194- . await ?;
216+ {
217+ let sql = if NO_DEFERRABLE_ON_READ . load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
218+ "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY"
219+ } else {
220+ "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE"
221+ } ;
222+ conn. execute ( sql) . await ?;
223+ }
195224
196225 Ok ( ( ) )
197226 }
0 commit comments