Skip to content

fix: prevent SQLITE_BUSY by limiting to single connection#37

Merged
mrz1836 merged 1 commit into
bsv-blockchain:mainfrom
mboyd1:sqlite
Mar 26, 2026
Merged

fix: prevent SQLITE_BUSY by limiting to single connection#37
mrz1836 merged 1 commit into
bsv-blockchain:mainfrom
mboyd1:sqlite

Conversation

@mboyd1
Copy link
Copy Markdown
Contributor

@mboyd1 mboyd1 commented Mar 25, 2026

SetMaxOpenConns(1) serializes writes through one connection, eliminating SQLITE_BUSY errors under concurrent HTTP load. Also adds cache_size, mmap_size, and temp_store pragmas for better throughput.

What Changed

  • Set db.SetMaxOpenConns(1) in the SQLite store to serialize all database access through a single connection
  • Added cache_size=-64000 (64MB page cache), mmap_size=268435456 (256MB memory-mapped I/O), and temp_store=MEMORY pragmas

Why It Was Necessary

  • Under concurrent POST traffic to /tx and /txs, multiple goroutines attempted simultaneous writes to SQLite
  • SQLite only supports a single writer at a time — concurrent write attempts returned SQLITE_BUSY (5) even with the existing 5s busy_timeout, causing HTTP 500 responses: {"error":"failed to store status:
    failed to insert status: database is locked (5) (SQLITE_BUSY)"}
  • The additional pragmas compensate for the single-connection bottleneck by reducing disk I/O per query

Testing Performed

  • All existing go test ./... pass
  • Deployed to production server receiving live transaction traffic
  • SQLITE_BUSY errors eliminated after deployment

Impact / Risk

  • Low risk — single-connection mode is SQLite's recommended configuration for server workloads with WAL mode
  • Write throughput is serialized but not degraded in practice since SQLite was already single-writer; this just moves the queuing from the SQLite lock manager to Go's connection pool
  • Read performance is unaffected — WAL mode allows concurrent reads from the same connection

Notifications

SetMaxOpenConns(1) serializes writes through one connection, eliminating
SQLITE_BUSY errors under concurrent HTTP load. Also adds cache_size,
mmap_size, and temp_store pragmas for better throughput.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mboyd1 mboyd1 requested a review from mrz1836 as a code owner March 25, 2026 15:09
@github-actions github-actions Bot added fork-pr PR originated from a forked repository requires-manual-review PR or issue requires manual review by a maintainer or security team labels Mar 26, 2026
@github-actions
Copy link
Copy Markdown

👋 Thanks, @mboyd1!

This pull request comes from a fork. For security, our CI runs in a restricted mode.
A maintainer will triage this shortly and run any additional checks as needed.

  • 🏷️ Labeled: fork-pr, requires-manual-review
  • 👀 We'll review and follow up here if anything else is needed.

Thanks for contributing to bsv-blockchain/arcade! 🚀

Copy link
Copy Markdown
Collaborator

@mrz1836 mrz1836 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mrz1836 mrz1836 merged commit 1d8432b into bsv-blockchain:main Mar 26, 2026
44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fork-pr PR originated from a forked repository requires-manual-review PR or issue requires manual review by a maintainer or security team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants