「psycopg2」を介したPostgreSQLのトランザクションは、カーソルごとまたは接続ごとですか?


10

psycopg2データベースAPI を使用してPostgreSQL 9.3で作業しています。

DB APIを最小分離レベル(「自動コミット」モード)に設定していて、SQLを介して直接自分のトランザクションを管理しています。例:

cur = self.conn.cursor()
cur.execute("BEGIN;")
cur.execute("SELECT dbId, downloadPath, fileName, tags FROM {tableName} WHERE dlState=%s".format(tableName=self.tableName), (2, ))
ret = cur.fetchall()
cur.execute("COMMIT;")

基本的に、トランザクションはcur.execute("BEGIN;")そのカーソルだけに限定されていますか、それとも接続全体に対するものself.conn.cursor()ですか()?

私が行っているより複雑なことのいくつかは、論理的に機能に分解する複数の個別のデータベース操作を含みます。これはすべて、接続をメンバーとして持つクラス内にあるため、各関数内にカーソルを作成する方がはるかに便利です。ただし、トランザクション内でカーソルを作成する方法がわかりません。

基本的に、トランザクションが接続ごとの場合、トランザクション内で多数のカーソルをオンザフライで作成できます。カーソルごとの場合は、カーソルをあちこちに移動する必要があります。どっち?

あなたが呼び出すことができるという事実はかかわらドキュメントは、これに触れていないconnection.commit()私が作る、かなりのトランザクション制御を接続ごとで自信を持って。

回答:


7

トランザクションはセッションごと、つまり接続ごとです。

PostgreSQLはトランザクションの一時停止と再開をサポートしていないため、psycopg2は暗黙的に新しい接続をバッ​​クグラウンドで作成しない限り、カーソルごとにトランザクションを作成できませんでした。

実際には、psycopg2のカーソルは特に便利だとは思いません。サーバーからのインクリメンタルフェッチを使用していない場合は、結果セットを保持できますが、他の多くの用途には適していません。

なぜ手動で発行beginし、commitしかし、むしろそれらの接続方法を使用するよりも?


ドキュメントからのAFICT、「DB API」モデル全体は、実際には明示的なトランザクションをまったくサポートしていません。
架空の名前

1
@FakeName明示的に指定する必要はありませんbegin。開いているトランザクションがない場合は、新しいトランザクションが開始されます。あなただけのcommitトランザクションを描くために。つまり、DB-APIモデル明示的なトランザクションをサポートしています。
クレイグリンガー、2014

1
特に指定しないでDB APIが自動的に実行している場合、それは非常に暗黙の始まりです。また、(質問で述べたように)自動コミットモードを使用しているので、これらの自動ステートメントは必要ないので、それは無関係ですBEGINpsycopg2それぞれに新しいトランザクションを作成したくありませんSELECT
偽名

TL; DR基本的に、A。私はそのように夢中になっているので、進行中のすべてのトランザクションの正確なスコープを知りたいです。B。デバッグに役立ちます。
偽名

1
私はこれで奇妙なバグがポップアップするのを見ても驚かないでしょう。私の知る限りの自動コミットは、実際にあることを意味する自動コミットしませ手動トランザクション管理。トランザクションスコープを手動で管理する必要がある場合、エクストラBEGINは無害であり、PostgreSQLによってで無視されますWARNING: there is already a transaction in progress
クレイグリンガー、2014

1

psycopg2のドキュメントから:

Psycopgでは、トランザクションは接続クラスによって処理されます。デフォルトでは、コマンドがデータベースに初めて送信されたときに(接続によって作成されたカーソルの1つを使用して)、新しいトランザクションが作成されます。次のデータベースコマンドは、最初のカーソルによって発行されたコマンドだけでなく、同じ接続によって作成されたすべてのカーソルによって発行されたコマンドと同じトランザクションのコンテキストで実行されます。コマンドが失敗した場合、トランザクションは中止され、rollback()メソッドが呼び出されるまでコマンドは実行されません。

同時に、バージョン2.4.2以降、次のautocommit属性があります(強調が追加されています)。

読み取り/書き込み属性:の場合True、ドライバーはトランザクションを処理せず、バックエンドに送信されるすべてのステートメントは即時に有効になります。False 最初のコマンド実行時に新しいトランザクションが開始された場合:メソッドを実行するcommit()rollback()、トランザクションを終了するために手動で呼び出す必要があります。

自動コミットモードは、CREATE DATABASEまたはなどのトランザクションの外部で実行する必要があるコマンドを実行するのに役立ちますVACUUM

デフォルトは、FalseDBAPI仕様に従って(手動コミット)です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.