Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot VACUUM from within a transaction [SQL: 'vacuum;'] #109

Closed
tardyp opened this issue Feb 1, 2017 · 5 comments
Closed

cannot VACUUM from within a transaction [SQL: 'vacuum;'] #109

tardyp opened this issue Feb 1, 2017 · 5 comments

Comments

@tardyp
Copy link

tardyp commented Feb 1, 2017

Opening an issue here, as I am out of ideas for this:
buildbot/buildbot#2705

I can see in f254c53
that checkVacuum unit test have been removed, which looks suspicious to me.

Anyway, in the buildbot code, I am trying to compact the database by first compressing some of of a table, then I call the vacuum; function in order to get actual database size improvement.
It did work until python3.6, and now whatever I do it will raise:

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) cannot VACUUM from within a transaction [SQL: 'vacuum;']

I did try to add conn.commit() before vacuum, but it says we are not in a transaction, which is also confirmed by Connection.in_transaction == False

The only way to fix this is to restore old behaviour, as implemented in the PR.

please advise

@ghost
Copy link

ghost commented Feb 5, 2017

It's a bug in pysqlite and Python 3.6.0's sqlite3 module.
(fixed in Python 3.6.1, see http://bugs.python.org/issue28518)

A workaround is:

You can set isolation_level = None in sqlite3.connect() parameters, then sqlite3 module will not begin a transaction implicitly.

Another way is disabling auto-begin-transaction temporarily:
sql.isolation_level = None
sql.execute('VACUUM')
sql.isolation_level = '' # <- note that this is the default value of isolation_level

@tardyp
Copy link
Author

tardyp commented Feb 6, 2017

thanks! the workaround actually worked for us buildbot/buildbot#2738

rkdarst added a commit to CxAalto/gtfspy that referenced this issue Feb 28, 2017
- Python 3.6 switches the behavior of transaction handling (no longer
  auto-committing before schema modifying commands).  There are some
  weird bugs where it doesn't know a transaction is open and doesn't
  commit, or something like that.  Just commiting manually creates
  other errors.
- This is a workaround that works on both python3.6 and older python.
- Possibly related things, but they don't contain enough to solve it:
  ghaering/pysqlite#109
  buildbot/buildbot#2738
lxnay referenced this issue in Sabayon/entropy Nov 4, 2018
geaaru added a commit to geaaru/entropy that referenced this issue Nov 4, 2018
pysqlite has a bug on use VACUUM with py3.6 (see ghaering/pysqlite#109)

Hereinafter, exception related to eit push --quick --force <REPO> command:

Traceback (most recent call last):
  File "/usr/lib/entropy/lib/entropy/db/sql.py", line 166, in _proxy_call
    return method(*args, **kwargs)
sqlite3.OperationalError: cannot VACUUM from within a transaction

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/eit", line 17, in <module>
    main()
  File "/usr/lib/entropy/server/eit/main.py", line 114, in main
    exit_st = func(*func_args)
  File "/usr/lib/entropy/server/eit/commands/command.py", line 237, in _call_exclusive
    return func(server)
  File "/usr/lib/entropy/server/eit/commands/push.py", line 172, in _push
    rc = self._push_repo(entropy_server, repository_id)
  File "/usr/lib/entropy/server/eit/commands/push.py", line 184, in _push_repo
    rc = self.__push_repo(entropy_server, repository_id)
  File "/usr/lib/entropy/server/eit/commands/push.py", line 309, in __push_repo
    sts = self.__sync_repo(entropy_server, repository_id)
  File "/usr/lib/entropy/server/eit/commands/push.py", line 262, in __sync_repo
    enable_download = False, force = self._force)
  File "/usr/lib/entropy/lib/entropy/server/interfaces/mirrors.py", line 1673, in sync_repository
    enable_upload, enable_download, force = force)
  File "/usr/lib/entropy/lib/entropy/server/interfaces/db.py", line 231, in update
    enable_upload, enable_download, force = force).update()
  File "/usr/lib/entropy/lib/entropy/server/interfaces/db.py", line 404, in update
    rc, fine_uris, broken_uris = self._sync()
  File "/usr/lib/entropy/lib/entropy/server/interfaces/db.py", line 1873, in _sync
    broken_uris = self._upload(uris)
  File "/usr/lib/entropy/lib/entropy/server/interfaces/db.py", line 1529, in _upload
    self._shrink_and_close(dbconn)
  File "/usr/lib/entropy/lib/entropy/server/interfaces/db.py", line 1234, in _shrink_and_close
    entropy_repository.vacuum()
  File "/usr/lib/entropy/lib/entropy/db/sqlite.py", line 703, in vacuum
    self._cursor().execute("vacuum")
  File "/usr/lib/entropy/lib/entropy/db/sqlite.py", line 58, in execute
    cur = self._proxy_call(self._cur.execute, *args, **kwargs)
  File "/usr/lib/entropy/lib/entropy/db/sql.py", line 173, in _proxy_call
    raise OperationalError(err)
entropy.db.exceptions.OperationalError: cannot VACUUM from within a transaction
@berkerpeksag
Copy link

FYI: This bug has already been fixed in the standard library version of sqlite3.

@ghaering
Copy link
Owner

You are much better off using either the standard library sqlite3 or apsw at this point. I haven't maintained this project for years.

@MarkC-b3d
Copy link

I encountered a similar issue with python 3.10.4 and sqlite3

I was able to fix it with isolation_level=None:

def remove_active_job():
    conn = sqlite3.connect('queue.db', isolation_level=None)
    c = conn.cursor()
    c.execute("DELETE FROM active WHERE ROWID=1")
    c.execute("VACUUM")
    conn.commit()
    conn.close()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants