Psycopg2|VACUUMやプロシージャのCALLでエラーしたときの対処法
PythonのPostgreSQL用データベースアダプタであるPsycopg2で、VACUUMやプロシージャをCALLするSQLを実行すると下のようなエラーが発生することがあります。
psycopg2.errors.ActiveSqlTransaction: VACUUM cannot run inside a transaction block
今回はこのようなエラーが発生した場合の対処法について説明します。
原因
下のPsycopg2の公式ドキュメントにもある通り、いくつかのコマンド(CREATE DATABASE、VACUUM、トランザクション制御を使用したストアド プロシージャのCALLなど)はトランザクション外で実行する必要がありますが、通常の使い方では自動的にトランザクション内でSQLが実行されるためエラーが発生します。
A few commands (e.g. CREATE DATABASE, VACUUM, CALL on stored procedures using transaction control…) require to be run outside any transaction: in order to be able to run these commands from Psycopg, the connection must be in autocommit mode: you can use the autocommit property.
対処法
autocommit
プロパティにTrue
を設定して自動コミットモードでSQLを実行するようにします。
サンプルコード
conn = psycopg2.connect(<接続文字列>)
conn.autocommit = True
cur = conn.cursor()
cur.execute("VACUUM ANALYZE <スキーマ.テーブル>;")
注意点としてwith
を一緒に使用してしまうと、自動コミットモードにならないらしく、エラーが発生します。
NGサンプルコード
## NGパターン①
conn = psycopg2.connect(<接続文字列>)
with conn:
conn.autocommit = True
with conn.cursor() as cur
cur.execute("VACUUM ANALYZE <スキーマ.テーブル>;")
## NGパターン②
conn = psycopg2.connect(<接続文字列>)
with conn:
conn.autocommit = True
cur = conn.cursor()
cur.execute("VACUUM ANALYZE <スキーマ.テーブル>;")