SQLite (Python apsw) не может выполнить откат, потому что он занят - PullRequest
2 голосов
/ 04 августа 2011

Я работаю с базой данных SQLite, используя привязки Python apsw.Код выглядит так:

with apsw.Connection(path) as t:
    c = t.cursor()
    c.execute(...)
    ... more code ...
    if c.execute(...).next()[0]:
        raise Exception

Я ожидаю, что оператор with установит точку сохранения, а оператор raise откатит до этой точки сохранения (или, если нечего вызвать, подтвердит транзакцию),Он совершает просто отлично, но когда есть что-то для raise, он отказывается откатываться с:

BusyError: BusyError: cannot rollback savepoint - SQL statements in progress

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

SQLite 3.7.7.1, соответствующий apsw, Python 2.7.

Ответы [ 2 ]

3 голосов
/ 24 июня 2014

Это проблема в самом SQLite. Это было исправлено в марте 2012 года, в версии 3.7.11. Из журнала изменений :

Ожидающие операторы больше не блокируют ROLLBACK. Вместо этого ожидающий оператор вернет SQLITE_ABORT при следующем доступе после ROLLBACK.

3 голосов
/ 04 августа 2011

Ну, я нашел это:

if c.execute(...).next()[0]:
    raise Exception

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

if c.execute(...).next()[0]:
    c.close()
    raise Exception

или неявно, путем считывания всех данных:

if list(c.execute(...))[0][0]:
    raise Exception

ОБНОВЛЕНИЕ.Для удобства я написал класс Python, который включает apsw.Cursor и предоставляет менеджер контекста , поэтому я могу написать:

with Cursor(connection) as c:
    c.execute(...)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...