Предотвращение блокировки базы данных sqlite3 - PullRequest
6 голосов
/ 05 ноября 2010

У меня есть многопоточное приложение, которое использует sqlite (3.7.3)

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

Позвольте мне описать, что я строю. Извините, код отсутствует, он слишком большой и сложный.

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

Каждая строка в таблице в базе данных имеет путь к файлу, который указывает на ресурс + другие атрибуты, связанные с этим ресурсом.

3 поля примечания: читатели, статус и del.

Считыватели увеличиваются каждый раз, когда поток читает из ресурса, но только если статус> 0 и del = 0.

Так что у меня есть SQL, который делает

UPDATE resource set readers=readers+1 where id=? AND del=0 AND status>0

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

Я попытался включить в транзакцию и обновление, и выбор, но это не помогло. Я проверил, что я звоню финализировать мои заявления тоже.

Теперь я подумал, что sqlite сериализуется по умолчанию. Я пробовал пару открытых режимов, но все равно получаю ту же ошибку.

И прежде чем вы спросите, нет, я не собираюсь идти на mysql. Мне абсолютно необходим нулевой конфиг.

Может ли кто-нибудь дать несколько советов о том, как избежать такого рода проблем? я должен переместить блокировку читателей из БД? Если я это сделаю, каким механизмом я должен заменить его? Я использую Linux под C ++ и с доступной библиотекой boost.

EDIT: Интересно, что добавление COMMIT после моего обновленного звонка значительно улучшило ситуацию.

Ответы [ 2 ]

2 голосов
/ 05 ноября 2010

Когда вы открываете базу данных, вы должны настроить «тайм-аут занятости»

int sqlite3_busy_timeout(sqlite3*, int ms);

http://www.sqlite.org/c3ref/busy_timeout.html

1 голос
/ 05 ноября 2010

Первый вопрос: вы пытаетесь использовать одно соединение со всеми восемью потоками?Если это так, убедитесь, что каждый поток имеет свое собственное соединение.Я не знаю ни одной базы данных, которой это нравится.

Также посмотрите FAQ: http://www.sqlite.org/faq.html

Очевидно, SQLite должен быть скомпилирован с опцией препроцессора SQLITE_THREADSAFE, установленной в 1. Ониесть способ определить, является ли это вашей проблемой.

Другая проблема заключается в том, что запись может происходить только из одного процесса безопасно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...