Ryota Kondo

Ryota Kondo

2024/01/20

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.

引用元:Basic module usage — Psycopg 2.9.9 documentation

対処法

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 <スキーマ.テーブル>;")

参考

この記事は以下の情報を参考にしました。

関連タグの記事

Ryota Kondo
Ryota Kondo

システムエンジニア・プログラマー|このブログサイトの運営もしており、思いついたことをまとめて記事を書いています💡|Twitterのフォローはお気軽に