Одновременный BEGIN – SELECT – INSERT вызывает мгновенную ошибку SQLite3.7.6 «база данных заблокирована», переопределяя время ожидания занятости? - PullRequest
2 голосов
/ 14 мая 2011

В консоли sqlite3:

sqlite>
    CREATE TABLE items (id PRIMARY KEY);
    BEGIN;
    SELECT * FROM items;
    INSERT INTO items VALUES(78);
sqlite> _

А потом во второй консоли:

sqlite>
    .timeout 10000;
    BEGIN;
    SELECT * FROM items;
    INSERT INTO items VALUES(78);
Error: database is locked
sqlite> _

«База данных заблокирована» - ошибка происходит мгновенно, что не может быть правильным, верно?

Если я опущу SELECT во второй консоли, обработчик занятости будет ждать 10 секунд при установке INSERT. Я обнаружил, что использование BEGIN EXCLUSIVE также заставляет вторую транзакцию ждать 10 секунд, но затем в BEGIN-операторе. (К которому я решил как обходной путь.)

Мой вопрос: это ошибка или так и должно быть? Если это ожидаемое поведение, то почему?

Спасибо!

(SQLite v3.7.6)

Ответы [ 2 ]

2 голосов
/ 10 февраля 2015

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

BEGIN EXCLUSIVE получает эксклюзивную блокировку сразу, вместо ожидания первого запроса, что объясняет разницу, которую вы видите.

Вам следует следить за заблокированной базой данных (SQLITE_BUSY) во время транзакций, а также выполнить откат и повторить попытку, если это произойдет. Обработчик времени ожидания не защитит их.

0 голосов
/ 27 июня 2011

Да, это нормально. Пожалуйста, прочитайте: http://www.sqlite.org/lockingv3.html

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