Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlite in-memory databases do not seem to work with connection pools #2510

Open
lovasoa opened this issue May 21, 2023 · 4 comments
Open

sqlite in-memory databases do not seem to work with connection pools #2510

lovasoa opened this issue May 21, 2023 · 4 comments
Labels

Comments

@lovasoa
Copy link
Contributor

lovasoa commented May 21, 2023

Hello,
I am working on SQLPage, that uses sqlx, and where users can configure their own database connections.

I noticed that when using a connection pool and an in-memory sqlite database, migrations are only applied on whatever connection is made initially, and new connections returned by the connection pool are to new different empty databases.
This is a nasty bug, because when you test the system initially, everything works, but only when the initial connection exceeds its idle_timeout, a new connection is successfully returned, which is also a valid connection, but to a completely different database.

A temporary fix is to use idle_timeout(None), but when I do that, I notice a leak of database connections under high load, and at some point all connections are exhausted and the system stays forever in a state where any try to acquire a new connection results in a timeout, even after the peak load has passed.

@lovasoa lovasoa added the bug label May 21, 2023
@mdegel
Copy link

mdegel commented Oct 6, 2023

I have experienced the same / a very similar issue (sqlx 0.7.2).

I have some code similar to this:

sqlx::any::install_default_drivers();
let pool = AnyPoolOptions::new()
    .max_connections(2)
    .connect("sqlite::memory:")
    .await?;
migrate!("db/migrations").run(&pool).await?;

This code runs without issues (no errors). Attempting to access the DB later yields errors like these for tables that should have been created during migration:

SqliteError { code: 1, message: "no such table: artifacts" }

For me, setting idle_timeout(None) on the pool (as described above) didn't have any impact, meaning the error stayed the same. What prevents the error for me, is explicitly disabling parallel connections, via .max_connections(1).

@mdegel
Copy link

mdegel commented Oct 6, 2023

Looking into it a bit further from earlier issues this seems to be an SQLite limitation: #362 (comment)

@kyrias
Copy link

kyrias commented Oct 6, 2023

That comment should not be relevant anymore because shared mode is supposed to be used by default, but there appears to be something strange going on when using AnyPool where even explicitly enabling the shared cache with sqlite::memory:?cache=shared doesn't work. Using a named in-memory database does appear to work though: sqlite:file:foo?mode=memory&cache=shared.

@hoxxep
Copy link
Contributor

hoxxep commented Apr 3, 2024

A potential workaround could be to set min_connections to a larger number, which shouldn't leak connections in the same way as idle_timeout. In my limited testing of this workaround, 3 appears to be enough connections.

// define in memory DB connection options
let sqlite_opts = SqliteConnectOptions::from_str(":memory:").unwrap();

// min_connections = 3 to prevent the DB from being wiped randomly
let pool = SqlitePoolOptions::new()
    .min_connections(3)
    .max_connections(10)  // default is 10
    .connect_with(sqlite_opts)
    .await?;

I don't know if this will fix all cases. I thought the pool could be dipping below min_connections, which may drop the in memory DB when it reaches 0 connections — I haven't looked at the code to verify any of this though.

Edit: Sadly it's not a complete fix and the issue still reoccurs, but slightly less frequently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants