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 database is locked error #1670

Open
dukhaSlayer opened this issue Jan 9, 2025 · 3 comments
Open

SQLite database is locked error #1670

dukhaSlayer opened this issue Jan 9, 2025 · 3 comments

Comments

@dukhaSlayer
Copy link
Contributor

dukhaSlayer commented Jan 9, 2025

By default, SQLite doesn't support multiple connections.
It can be enabled either with a shared cache or write-ahead log feature.

Default connection # for Hikari: DEFAULT_POOL_SIZE = 10,
which under the load produces exceptions:
org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked)

I'd advise doing

config.setMaximumPoolSize(1);

in org.asamk.signal.manager.storage.Database#getHikariDataSource or trying enabling WAL with PRAGMA (not sure it will solve the issue completely though, if two connections will try to write simultaneously).

More info:
https://stackoverflow.com/questions/10325683/can-i-read-and-write-to-a-sqlite-database-concurrently-from-multiple-connections

@dukhaSlayer
Copy link
Contributor Author

Also wanted to ask why it is using IMMEDIATE transaction mode? :)

        sqliteConfig.setTransactionMode(SQLiteConfig.TransactionMode.IMMEDIATE);

@GooseBravo101
Copy link

Unfortunately setting max pool size to 1 makes things worse, or just reveals a bigger problem. Instead of randomly raising the exception, it just times out at first big query like key value store

Lately i am having a lot of SQLITE_BUSY exceptions in signal-cli, my application stops at least once a day because db was busy, and doesn't want to recover.
I tried hiding all db communications in synchronized environment, didn't help, but i noticed that it usually times out at setting autocommit to false, trying to not use autocommit=false/commit pair didn't help either, it still breaks time after time

AsamK added a commit that referenced this issue Jan 14, 2025
@AsamK
Copy link
Owner

AsamK commented Jan 14, 2025

sqlite does support multiple read connections at the same time, though every write will block the database.
Setting the pool size to 1 will prevent any parallel read connections.
IMMEDIATE transaction mode is used so that explicitly started transactions are immediately started as write transactions. The sqlite default behavior would be to start transactions as readonly and upgrade them to write transactions when an update statement is executed, which can lead to unpredictable behavior if the upgrade fails.
It times out at setting autocommit to false because that's when the explicit write transaction is started. Disabling that can lead to data corruption due to not using a transaction for updating data.

Enabling WAL might help here. I've enabled WAL mode in e11e093, can you try the latest master if it works better?

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

No branches or pull requests

3 participants