Skip to content

Commit c2e1d5c

Browse files
committed
perf: optimize SQLite WAL connection pragmas
1 parent c039c35 commit c2e1d5c

1 file changed

Lines changed: 19 additions & 19 deletions

File tree

  • backend/open_webui/internal

backend/open_webui/internal/db.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import json
33
import logging
4-
from contextlib import asynccontextmanager, contextmanager
4+
from contextlib import asynccontextmanager, contextmanager, closing
55
from typing import Any, Optional
66

77
from open_webui.internal.wrappers import register_connection
@@ -108,6 +108,22 @@ def _make_async_url(url: str) -> str:
108108
# Alembic, peewee migration, health checks)
109109
# ============================================================
110110

111+
# Shared SQLite connection handler, used by both sync and async engines
112+
def _sqlite_on_connect(dbapi_connection, connection_record):
113+
with closing(dbapi_connection.cursor()) as cursor:
114+
if DATABASE_ENABLE_SQLITE_WAL:
115+
cursor.execute('PRAGMA journal_mode=WAL')
116+
# synchronous=NORMAL is safe with WAL: durable on app crash, may roll back
117+
# last transactions on OS crash or power loss; acceptable for most web apps.
118+
cursor.execute('PRAGMA synchronous=NORMAL')
119+
cursor.execute('PRAGMA journal_size_limit=67108864') # Cap WAL file at 64 MB
120+
cursor.execute('PRAGMA cache_size=-32768') # 32 MB page cache, per connection
121+
cursor.execute('PRAGMA temp_store=MEMORY')
122+
cursor.execute('PRAGMA busy_timeout=5000') # Retry up to 5 s on lock contention
123+
else:
124+
cursor.execute('PRAGMA journal_mode=DELETE')
125+
126+
111127
# Handle SQLCipher URLs
112128
if SQLALCHEMY_DATABASE_URL.startswith('sqlite+sqlcipher://'):
113129
database_password = os.environ.get('DATABASE_PASSWORD')
@@ -154,16 +170,7 @@ def create_sqlcipher_connection():
154170

155171
elif 'sqlite' in SQLALCHEMY_DATABASE_URL:
156172
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={'check_same_thread': False})
157-
158-
def on_connect(dbapi_connection, connection_record):
159-
cursor = dbapi_connection.cursor()
160-
if DATABASE_ENABLE_SQLITE_WAL:
161-
cursor.execute('PRAGMA journal_mode=WAL')
162-
else:
163-
cursor.execute('PRAGMA journal_mode=DELETE')
164-
cursor.close()
165-
166-
event.listen(engine, 'connect', on_connect)
173+
event.listen(engine, 'connect', _sqlite_on_connect)
167174
else:
168175
if isinstance(DATABASE_POOL_SIZE, int):
169176
if DATABASE_POOL_SIZE > 0:
@@ -212,14 +219,7 @@ def get_session():
212219
ASYNC_SQLALCHEMY_DATABASE_URL,
213220
connect_args={'check_same_thread': False},
214221
)
215-
216-
if DATABASE_ENABLE_SQLITE_WAL:
217-
218-
@event.listens_for(async_engine.sync_engine, 'connect')
219-
def _set_sqlite_wal(dbapi_connection, connection_record):
220-
cursor = dbapi_connection.cursor()
221-
cursor.execute('PRAGMA journal_mode=WAL')
222-
cursor.close()
222+
event.listen(async_engine.sync_engine, 'connect', _sqlite_on_connect)
223223
else:
224224
if isinstance(DATABASE_POOL_SIZE, int):
225225
if DATABASE_POOL_SIZE > 0:

0 commit comments

Comments
 (0)