2009-05-18 2 views
4

У меня запущено несколько потоков, каждая из которых пытается выполнить INSERTS в одной базе данных SQLite. Каждый поток создает свое собственное соединение с БД. Каждый из них создает команду, открывает транзакцию, выполняя некоторые ВСТАВКИ, а затем закрывает транзакцию. Кажется, что второй поток для попытки чего-либо получает следующее SQLiteException: файл базы данных заблокирован. Я попробовал разворачивать INSERTS из транзакции, а также сузить область INSERTS, содержащуюся в каждом коммите, без реального эффекта; последующий доступ к файлу db вызывает одно и то же исключение.Сложность, выполняющая параллельные ВСТАВКИ на базе SQLite в C#

Любые мысли? Я в тупике, и я не уверен, где искать дальше ...

ответ

5

Обновите свой код вставки, чтобы он обнаружил исключение, указывающее на блокировку базы данных, он немного ждет и снова пытается. Увеличивайте время ожидания на случайные приращения каждый раз (алгоритм «случайного отсрочка»). Это должно позволить потокам каждого захватить глобальную блокировку записи. Производительность будет плохой, но код должен работать без существенных изменений.

Однако SQLite не подходит для высококонкурентной модификации. У вас есть два постоянных решение:

  • Переход к «реальным» базам данных, например, PostgreSQL или MySQL
  • сериализовать все изменения в базе данных через одну нити, чтобы избежать изменений в SQLITE.
+0

классный .. я считал это, но действительно ли это гарантирует, что он никогда не будет заблокирован? я чувствую, что он просто займет больше времени (другими словами, уменьшит шансы), чтобы снова запереться. im работает на очень большом количестве данных, и процесс займет несколько часов, если не дни ... –

+0

также, когда вы говорите, что вы очень одновременно, что именно вы имеете в виду? мое приложение будет работать от 1 до 20 из этих потоков при нормальном использовании. это считается высокой параллелизмом? –

+1

Если сериализован в один поток, он не будет иметь ошибок при блокировке. Кроме того, если вы повторите попытку блокировки ошибок, они не будут препятствовать завершению программы. SQLite не предназначен для параллелизма, но его можно заставить работать для нескольких потоков, которые часто не входят в INSERT. Если у вас есть 3+ темы, которые все вставляют, вы должны использовать другую базу данных. –

1

Две вещи, чтобы проверить:

1) Подтверждено, что ваша версия SQLite была собрана с НИТИ поддержкой

2) Убедитесь, что вы не открывая базу данных ЭКСКЛЮЗИВ

0

Я не был делая это на C#, но, скорее, в Android, но я обошел эту ошибку «база данных заблокирована», сохраняя базу данных sqlite всегда открытой в классе оболочки, которой она владеет, на протяжении всего жизненного цикла класса-оболочки. Каждая вставка, сделанная в этом классе, может быть в своем потоке (потому что, в зависимости от вашей ситуации хранения данных, SD-карты и памяти устройства и т. Д., Запись db может занять много времени), и я даже попытался ее дросселировать, дюжина вставлять потоки сразу, и каждый из них обрабатывался очень хорошо, потому что метод вставки не должен был беспокоиться об открытии/закрытии БД.

Я не уверен, что устойчивые жизненные циклы DB считаются хорошим стилем (хотя в большинстве случаев это может считаться плохим), но на данный момент он работает очень хорошо.