SQLite SharedCache MultiThread читает
Я занимаюсь разработкой многопоточного приложения базы данных sqlite на виртуальной машине Ubuntu, для которой выделено 4 процессора. Я использую sqlite версии 3.7.13. Я создал тест, чтобы убедиться, что несколько потоков / соединений могут читать из базы данных одновременно.
У меня есть два исполняемых файла. Первый исполняемый файл просто создает базу данных, создает 1 таблицу в этой базе данных, вставляет 50 элементов в эту таблицу и затем закрывает базу данных. Это совсем не предполагает многопоточности и просто предназначено для предоставления базы данных с записями в ней.
Второй исполняемый файл создает несколько потоков для чтения из базы данных и ожидает их завершения и записывает время, необходимое для завершения всех потоков. Каждый поток выполняет следующее: -создание соединения с базой данных с помощью sqlite_open_v2(), чтобы каждый поток имел свое собственное индивидуальное соединение с базой данных, созданной из первого исполняемого файла; -произвести 100000 SELECTS для одной таблицы базы данных (каждый запрос на выбор для одной строки в таблица) - закрыть соединение с базой данных
Когда я запустил этот тест с SQLITE_OPEN_READWRITE, указанным в качестве флагов для sqlite_open_v2 в каждом потоке, я получил следующие результаты для общего времени выполнения всех запросов:
1 темы - 0,65 секунды 2 темы - 0,70 секунды 3 темы - 0,76 секунды 4 темы - 0,91 секунды 5 темы - 1,10 секунды 6 темы - 1,28 секунды 7 темы - 1,57 секунды 8 темы - 1,78 секунды
Эти результаты были ожидаемыми, так как время немного увеличилось (вероятно, из-за переключения контекста между потоками и другими причинами), когда я добавляю потоки, что означает, что чтение в основном выполняется параллельно.
Однако, когда я запустил этот же тест с SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE для флагов, я получаю следующие результаты:
1 темы - 0,67 секунды 2 темы - 2,43 секунды 3 темы - 4,81 секунды 4 темы - 6,60 секунды 5 темы - 8,03 секунды 6 темы - 9,41 секунды 7 темы - 11,17 секунды 8 темы - 12,79 секунды
Из этих результатов видно, что что-то в режиме общего кэша предотвращает одновременное чтение нескольких данных в базе данных. Я убедился, что действительно разные потоки работают параллельно (чтение потока 4, чтение потока 8, чтение потока 2 и т. Д., А не поток 1 выполняет все свои чтения, поток 2 выполняет все свои чтения, поток 3 выполняет все свои чтения, так далее.). Однако, похоже, что чтения для каждой отдельной транзакции выполняются последовательно или что-то еще замедляет работу базы данных в общем кэше.
Почему я вижу такое большое увеличение времени, когда я добавляю потоки в режиме общего кэша, а не без него? Есть ли способ исправить это и по-прежнему использовать режим общего кэша?
Спасибо за любую помощь. Это высоко ценится.
1 ответ
В настоящее время я могу только сказать, что в shared cache mode
каждый поток делает дополнительный read mutex lock()
по каждому запросу несколько раз (блокировка в общем кэше, блокировка главной таблицы, блокировка запрошенной таблицы). Конечно, у него есть некоторые накладные расходы.
Чтобы избежать этого вы можете использовать PRAGMA read_uncommitted = true;
, но это может привести к противоречивым результатам запроса, если другое соединение с базой данных изменяет таблицу во время чтения, но это также означает, что транзакция чтения, открытая соединением в режиме чтения без фиксации, не может ни блокировать, ни блокироваться каким-либо другим соединением,
(Вы можете предоставить свой код?)