SQLite: совместное использование соединений по потокам для чтения и записи

У меня есть приложение, которое использует SQLite (версия 3.7.2) для хранения данных. У меня есть соединение SQLite, разделенное между несколькими потоками, которые записывают и читают из одного и того же SQLite db. SQLite скомпилирован с DSQLITE_THREADSAFE = 1, что означает, что SQLite находится в режиме Serialized.

Цитата из SQLite docs

Сериализованный: в сериализованном режиме SQLite можно безопасно использовать несколькими нити без ограничений.

Наоборот, запись SQLite Wiki гласит

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

Я попытался с примером приложения, которое порождает сотни потоков и разделяет дескриптор SQLite для чтения и записи, который работает нормально.

Итак, устаревшая запись в вики SQLite или SQLite, возможно, не сможет обрабатывать чтение и запись из разных потоков одновременно с помощью одного и того же соединения?

Ответ 1

ИЗМЕНИТЬ

DSQLITE_THREADSAFE = 2: многопоточный режим Термин "многопоточность" немного запутан в SQLite. Похоже, что в многопоточном режиме вы не можете обмениваться соединением с другими потоками, потому что само соединение не будет использовать мьютексы, чтобы предотвратить изменение одного потока, пока другой поток использует его.

DSQLITE_THREADSAFE = 1: сериализованный режим Однако в режиме serialized он блокирует файл данных и будет использовать мьютексы для управления доступом к общему соединению.

Из документов: ... когда SQLite скомпилирован с SQLITE_THREADSAFE = 1, библиотека SQLite сама будет сериализовать доступ к соединениям с базой данных и подготовленным операциям, чтобы приложение могло использовать одно и то же соединение с базой данных или один и тот же подготовленный оператор в разных потоках одновременно.

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

Источник: http://www.sqlite.org/c3ref/c_config_getmalloc.html#sqliteconfigmultithread

Привет!

Ответ 2

Неплохая идея поделиться одним соединением между несколькими потоками, когда у вас есть DSQLITE_THREADSAFE = 0

Представьте, что ваш THREAD 1 выполняет этот код:

1. connection.setAutoCommit(false);
2. statement.executeUpdate(sql);
3. connection.commit();

и ваш THREAD 2 выполняет этот код в одно и то же время:

1. connection.setAutoCommit(true);

Теперь, что, если инструкция 1 THREAD 2 выполняется точно ПЕРЕД инструкцией 3 РЕЗЬБЫ 1? Вероятно, вы получите SQLException с сообщением "база данных в режиме автоматической фиксации" (так как методы автоматической фиксации выполняются по одному и тому же объекту Connection).

Это означает, что нужно синхронизировать его руду кода, используя DSQLITE_THREADSAFE = 1

Использование пула соединений также будет лучшим, если вы собираетесь разработать многопоточный код, из которого вы можете получить более высокую производительность, когда решите выбрать другую СУБД.