Skip to content

Commit 5da0d5f

Browse files
committed
config: set synchronous to NORMAL for writes
- https://www.sqlite.org/wal.html#performance_considerations
1 parent 982f5f1 commit 5da0d5f

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

crates/sqlx-sqlite-conn-mgr/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,32 @@ queries.
142142
The operation is idempotent and safe to call across multiple sessions,
143143
allowing concurrent reads during writes.
144144

145+
**Synchronous Mode: NORMAL vs FULL**
146+
147+
When WAL mode is enabled, this library sets `PRAGMA synchronous = NORMAL`
148+
instead of `FULL` for the following reasons:
149+
150+
* **Performance**: `NORMAL` provides significantly better write performance
151+
(up to 2-3x faster) by reducing the number of fsync operations. With `FULL`,
152+
SQLite syncs after every checkpoint; with `NORMAL`, it syncs only the WAL file.
153+
154+
* **Safety in WAL mode**: `NORMAL` is safe in WAL mode because:
155+
* WAL transactions are atomic and durable at the WAL file level
156+
* The database file itself can be checkpointed asynchronously
157+
* A crash may corrupt the database file, but the WAL file remains intact
158+
and will be used to recover on next open
159+
* This is different from rollback journal mode where `NORMAL` could cause
160+
corruption
161+
162+
* **Mobile/Desktop Context**: For typical desktop and mobile applications,
163+
`NORMAL` provides the best balance of performance and safety. `FULL` is
164+
primarily needed for scenarios with unreliable storage hardware or when
165+
power loss can occur mid-fsync operation.
166+
167+
See [SQLite WAL Performance Considerations][wal-perf] for more details.
168+
169+
[wal-perf]: https://www.sqlite.org/wal.html#performance_considerations
170+
145171
4. **Exclusive Writes**: The write pool has `max_connections=1`, ensuring
146172
only one writer can exist at a time. Other callers to
147173
`acquire_writer()` will block (asynchronously) until the current writer

crates/sqlx-sqlite-conn-mgr/src/database.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ impl SqliteDatabase {
242242
.execute(&mut *conn)
243243
.await?;
244244

245+
// https://www.sqlite.org/wal.html#performance_considerations
246+
sqlx::query("PRAGMA synchronous = NORMAL")
247+
.execute(&mut *conn)
248+
.await?;
249+
245250
self.wal_initialized.store(true, Ordering::SeqCst);
246251
}
247252

@@ -563,6 +568,17 @@ mod tests {
563568
"Journal mode should be WAL after first acquire_writer"
564569
);
565570

571+
// Check sync setting
572+
let (sync,): (i32,) = sqlx::query_as("PRAGMA synchronous")
573+
.fetch_one(&mut *writer)
574+
.await
575+
.unwrap();
576+
577+
assert_eq!(
578+
sync, 1,
579+
"Sync mode should be NORMAL after first acquire_writer"
580+
);
581+
566582
drop(writer);
567583

568584
db.remove().await.unwrap();

0 commit comments

Comments
 (0)