2016-08-25 4 views
1

Работая над оптимизацией базы данных, мы разбиваем нашу базу данных на две базы данных: db и db2. Фоновый поток с низким приоритетом вставляется в db2. Некоторые из запросов на db соединены с db2, поэтому нам нужно привязать db2 к db. Мы включаем WAL, потому что хотим, чтобы все это было многопоточным.SQLite: запись в журнал записи (режим журнала WAL) с подключенной базой данных

SQLiteDatabase db = SQLiteDatabase.openDatabase(dbPath, ...); 
db.enableWriteAheadLogging(); 
db.execSQL("attach " + db2path + " as db2"); 

Чтобы понять проблему, мы запускаем простой тест на два потока. Первый поток вставляет строки в db, а второй поток выбирает из db. Каждый поток печатает временную дельта от предыдущего цикла и время, которое мы находились внутри базы данных.

thread 1 loop:        | thread 2 loop: 
    t1 = getTime()       | t1 = getTime() 
    db2.execSQL("insert into ....");  | db2.execSQL("select ...."); 
    t2 = t3        | t2 = t3 
    t3 = getTime()       | t3 = getTime() 
    log("i: "+(t3-t1)+", delta: "+(t2-t1)) | log("s: "+(t3-t1)+", delta: "+(t2-t1)) 

Мы видим, что выбранная нить блокирует вставочный поток. Это можно сделать, сделав огромный (и медленный) выбор и крошечную вставку. Вы увидите, что время вставки и дельта увеличиваются примерно до времени выбора. Если мы не запускаем медленные потоки, вставной поток значительно ускоряется.

Порывшись в исходный код SQLiteDatabase я нашел следующие строки в SQLiteDatabase#enableWriteAheadLogging():

// make sure this database has NO attached databases because sqlite's write-ahead-logging 
// doesn't work for databases with attached databases 
if (mHasAttachedDbsLocked) { 
    if (Log.isLoggable(TAG, Log.DEBUG)) { 
     Log.d(TAG, "this database: " + mConfigurationLocked.label 
       + " has attached databases. can't enable WAL."); 
    } 
    return false; 
} 

Теперь мои вопросы:

  1. Какой смысл комментария? Что именно не работает? Остается ли какой-то старый код? Документация ATTACH DATABASE (https://www.sqlite.org/lang_attach.html) явно указывает, что ATTACH + WAL в порядке (с небольшим оговоркой.)

  2. Почему код привязки Android пытается защитить нас от внутренних проблем SQLite? Как я вижу это, он должен быть тонким интерфейсом.

Редактировать: Я об этом как ошибка в AOSP issue tracker. Будет обновлен, если там появится ответ.

ответ

0

WAL позволяет читателям и писателю одновременно, но только из разных соединений. Вы никогда не должны использовать одно и то же соединение (объект SQLiteDatabase) из нескольких потоков.

Настройка WAL является постоянной; вам не нужно выполнять его каждый раз после открытия базы данных.

  1. Смысл комментария - это именно то, что он говорит. (Никто не гарантирует, что этот комментарий верен.)

  2. Иногда фреймворк Android пытается быть умным. Но вы можете просто выполнить PRAGMA journal_mode = WAL вручную.

+0

Вы не поняли мой вопрос. Я говорю о исходном коде объекта SQLiteDatabase. – grebulon

+0

И никто, кроме автора, не мог ответить на вопросы, как написано. –

+0

Надеюсь, они прочитали это, и я также спросил снаружи. – grebulon