Skip to content

Commit

Permalink
ServerDB, Meta: add support for SQLite WAL.
Browse files Browse the repository at this point in the history
Using SQLite's WAL (write-ahead log) can create less disk I/O while
still providing good consistency and durability.

This change uses SQLite's WAL with synchronous=NORMAL which can
can cause loss of transactions on power failure. Only the transactions
which haven't been synced to the disk by the OS are lost. The database
itself will still be in a consistent state, but it might not have all
recent changes.
  • Loading branch information
mkrautz committed Mar 5, 2017
1 parent b3df846 commit 0335c79
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
19 changes: 19 additions & 0 deletions scripts/murmur.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@
; murmur.sqlite in default locations or create it if not found.
database=

; Murmur defaults to using SQLite with its default rollback journal.
; In some situations, using SQLite's write-ahead log can be advantageous.
; If you encounter slowdowns when moving between channels and similar
; operations, enabling the SQLite WAL might help.
;
; To use SQLite's write-ahead log, set sqlite_val to one of the following
; values:
;
; 0 - Use SQLite's default rollback journal.
; 1 - Use write-ahead log with synchronous=NORMAL.
; If Murmur crashes, the database will be in a consistent state, but
; the most recent changes might be lost, if the operating system did
; not write them to disk yet. This option can improve Murmur's
; interactivity busy servers, or servers with slow storage.
; 2 - Use write-ahead log with synchronous=FULL
; All database writes are synchronized to disk when they are made.
; If Murmur crashes, the database will be include all completed writes.
;sqlite_wal=0

; If you wish to use something other than SQLite, you'll need to set the name
; of the database above, and also uncomment the below.
; Sticking with SQLite is strongly recommended, as it's the most well tested
Expand Down
3 changes: 3 additions & 0 deletions src/murmur/Meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ MetaParams::MetaParams() {
bRememberChan = true;
qsWelcomeText = QString();
qsDatabase = QString();
iSQLiteWAL = 0;
iDBPort = 0;
qsDBusService = "net.sourceforge.mumble.murmur";
qsDBDriver = "QSQLITE";
Expand Down Expand Up @@ -280,8 +281,10 @@ void MetaParams::read(QString fname) {
bForceExternalAuth = typeCheckedFromSettings("forceExternalAuth", bForceExternalAuth);

qsDatabase = typeCheckedFromSettings("database", qsDatabase);
bSQLiteWAL = typeCheckedFromSettings("sqlite_wal", bSQLiteWAL);

qsDBDriver = typeCheckedFromSettings("dbDriver", qsDBDriver);
bSQLiteWAL = typeCheckedFromSettings("sqlite_wal", bSQLiteWAL);
qsDBUserName = typeCheckedFromSettings("dbUsername", qsDBUserName);
qsDBPassword = typeCheckedFromSettings("dbPassword", qsDBPassword);
qsDBHostName = typeCheckedFromSettings("dbHost", qsDBHostName);
Expand Down
1 change: 1 addition & 0 deletions src/murmur/Meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class MetaParams {
int iBanTime;

QString qsDatabase;
int iSQLiteWAL;
QString qsDBDriver;
QString qsDBUserName;
QString qsDBPassword;
Expand Down
38 changes: 38 additions & 0 deletions src/murmur/ServerDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,44 @@ ServerDB::ServerDB() {
qFatal("ServerDB: Failed initialization: %s",qPrintable(e.text()));
}

// Use SQLite in WAL mode if possible.
if (Meta::mp.qsDBDriver == "QSQLITE") {
if (Meta::mp.iSQLiteWAL > 0 && Meta::mp.iSQLiteWAL <= 2) {
QSqlQuery query;

bool ok = false;
QString version;
SQLDO("SELECT sqlite_version();");
if (query.next()) {
version = query.value(0).toString();
}

QStringList splitVersion = version.split(QLatin1String("."));
int major = 0, minor = 0;
if (splitVersion.count() >= 3) {
major = splitVersion.at(0).toInt();
minor = splitVersion.at(1).toInt();
}
if (major >= 3 || (major == 3 && minor >= 7)) {
ok = true;
}

if (ok) {
SQLDO("PRAGMA journal_mode=WAL;");
if (Meta::mp.iSQLiteWAL == 1) {
SQLDO("PRAGMA synchronous=NORMAL;");
} else if (Meta::mp.iSQLiteWAL == 2) {
SQLDO("PRAGMA synchronous=FULL;");
}
qWarning("ServerDB: Configured SQLite for journal_mode=WAL, synchronous=NORMAL");
} else {
qWarning("ServerDB: Unable to use SQLite in WAL mode due to incompatible SQLite version %i.%i", major, minor);
}
} else {
qFatal("ServerDB: Invalid value '%i' for sqlite_wal. Please use 0 (no wal), 1 (wal), 2 (wal with synchronous=full)");
}
}

TransactionHolder th;

QSqlQuery &query = *th.qsqQuery;
Expand Down

0 comments on commit 0335c79

Please sign in to comment.