23

Serializable Isolation Level に関するPostgreSQL のマニュアル ページには、次のように記載されています。

[同様に] Repeatable Read レベルでは、このレベルを使用するアプリケーションは、シリアル化の失敗によるトランザクションの再試行に備える必要があります。

Repeatable Read または Serializable レベルでシリアライゼーション エラーが発生する条件は何ですか?

実行中の 2 つのインスタンスでシリアライゼーションの失敗を誘発しようとしましたpsqlが、トランザクションが一方のインスタンスによってコミットされたにもかかわらず、もう一方のインスタンスがシリアライズ可能なレベルのトランザクション内でコミットされ、もう一方のインスタンスがその変更をコミットすることに成功しました。どちらもレコードをテーブルに挿入しただけなので、もっと複雑なことを試す必要があるかもしれません。

基本的に、シリアライゼーションが失敗した場合に何が起こるか、およびシリアライゼーションの失敗がどのように発生するかを理解しようとしています。

4

4 に答える 4

11

シリアライゼーションの失敗には、多くの原因が考えられます。技術的には、2 つのトランザクション間のデッドロックはシリアライゼーション エラーの 1 つの形式であり、スキーマ (データベース構造) への同時変更がある場合、任意の分離レベルで発生する可能性があります。PostgreSQL について尋ねているので、PostgreSQL では、このタイプのシリアライゼーションの失敗は、他のものとは別の SQLSTATE '40P01' を取得することに注意してください。他のすべてのシリアル化の失敗は、'40001' を返します。この回答の残りの部分では、PostgreSQL におけるこれらの非デッドロックの種類に焦点を当てます。

ライブ レプリカ (「ホット スタンバイ」) の外では、これらは REPEATABLE READ と SERIALIZABLE の 2 つのより厳密な分離レベルでのみ発生します。REPEATABLE READ レベルでは、これらは書き込みの競合が原因でのみ発生します。2 つの同時トランザクションが同じ (既存の) 行を更新または削除しようとします。試行を行う最初のトランザクションは、行をロックして続行します。コミットすると、2 番目のトランザクションはシリアライゼーション エラーで失敗します。最初のトランザクションが何らかの理由でロールバックした場合、ブロックされたトランザクションは解放されて処理を続行し、その行に対して独自のロックを取得します。この動作は、トランザクション中の単一の「スナップショット」と組み合わせて、SNAPSHOT ISOLATION とも呼ばれます。

PostgreSQL バージョン 9.1 より前では、SERIALIZABLE トランザクションはまったく同じように機能していました。9.1 以降の PostgreSQL は、Serializable Snapshot Isolation と呼ばれる新しい手法を使用して、一連のシリアライズ可能なトランザクションの動作が、それらのトランザクションのシリアル (一度に 1 つずつ) 実行と完全に一致するようにします。9.1 で SERIALIZABLE トランザクションを使用する場合、アプリケーションは ROLLBACK を除くすべてのステートメントでのシリアライゼーションの失敗に備える必要があります。読み取り専用トランザクションや COMMIT でも同様です。詳細については、PostgreSQL のドキュメント ページ ( http://www.postgresql.org/docs/current/interactive/transaction-iso.html ) を参照するか、新しいより厳格な分離レベルでシリアル化の失敗がどのように発生するかの例を示す Wiki ページを参照してください。でhttp://wiki.postgresql.org/wiki/SSI

ホット スタンバイ機能を使用している場合、データの安定したビューを維持するためにデータベースがレプリケーションを長時間停止する必要がある長時間実行クエリがあると、読み取り専用レプリカでシリアライゼーション エラーが発生する可能性があります。レプリケートされたデータの「鮮度」と実行時間の長いクエリの許容範囲とのバランスを取るための構成設定があります。一部のユーザーは、複数のレプリカを作成して、最新のデータを保持できるようにし (同期レプリケーションを選択することさえあります)、必要に応じて別のレプリカを遅延させて、長時間実行されるクエリを処理することを希望する場合があります。

編集して別のリンクを提供する: 「 Serializable Snapshot Isolation in PostgreSQL」というタイトルの論文は、第 38 回超大規模データベースに関する国際会議で発表され、この実装の基礎を築いた論文への参照とともに、他のリンクよりも詳細と展望を提供します。

于 2012-04-02T22:21:47.503 に答える
9

このREPEATABLE READ例では、次のようになります。

準備段階:

psql-0> CREATE TABLE foo(key int primary key, val int);
CREATE TABLE
psql-0> INSERT INTO foo VALUES(1, 42);

アクションのインターリーブを示すpsql- X部分に注目してください。

psql-1> BEGIN ISOLATION LEVEL REPEATABLE READ;
psql-1> UPDATE foo SET val=val+1;
UPDATE 1
psql-2> BEGIN ISOLATION LEVEL REPEATABLE READ;
psql-2> UPDATE foo SET val=val+1;
*** no output, transaction blocked ***

psql-1> COMMIT;

psql-2> *** unblocks ***
ERROR:  could not serialize access due to concurrent update

SERIALIZABLEは PostgreSQL 9.1 のドキュメントにあり、ここからは問題ありません。

于 2011-10-09T18:26:52.300 に答える
5

これが誰かに役立つ場合のために、Freenode の #postgresql からのトランスクリプトを次に示します。

[14:36] <dtrebbien> シリアル化の失敗が発生する条件は?

[14:36] <dtrebbien> ^ シリアル化の失敗が発生する条件は?

[14:37] <dtrebbien> シリアライゼーションの失敗の条件を特定できる PostgreSQL 開発者はいますか?

[14:38] <peerce> http://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-SERIALIZABLE

[14:43] <dtrebbien> "シリアライズ可能な同時トランザクションのセットは、一度に 1 つずつ実行された場合と同じ効果があります"

[14:44] <dtrebbien> PostgreSQL エンジンが従うルールは何ですか?

[14:44] <dtrebbien> つまり、行が変更された場合、それは失敗を引き起こしますか?

[14:44] <johto> 9.1 のシリアライズ可能な分離モードは本当に複雑です

[14:45] <dtrebbien> わかった。

[14:45] <dtrebbien> 私も読んだのですが、Serializable レベルがどういうわけか「固定」されていました。

[14:45] <RhodiumToad> dtrebbien: 9.1 より前の基本的なルールは、現在の値が見えない行をトランザクションが変更しようとすると失敗するというものでした。

[14:46] <dtrebbien> RhodiumToad: 興味深いですね。

[14:46] <dtrebbien> また、値にアクセスしますよね?

[14:46] <selenamarie> dtrebbien: 他の人が言ったことに加えて、その背後にある基本的な前提は、依存関係のサイクルの検出です

[14:47] <dtrebbien> ああ。

[14:50] <dtrebbien> 9.1 では、分離レベルをトリガーするためのルールがより複雑になり、基本的に「偽陽性」のシリアライゼーション異常を削減したと言っても過言ではありませんか?

[14:51] <johto> より単純な規則がすべてのシリアライゼーションの異常をキャッチできなかったので、それらは複雑になりました

[14:51] <dtrebbien> ああ!分かりました。

[14:51] <dtrebbien> リリースノートに「修正済み」と書かれているのはそのためです。

[14:52] <RhodiumToad> dtrebbien: 非表示の値へのアクセスは、スナップショットの時点で表示されていた値を取得しただけなので、エラーではありませんでした。

[14:53] <RhodiumToad> dtrebbien: 読み取り専用のシリアル化可能なクエリは、スナップショット時点でのデータベースの静的状態を参照するだけです。

[14:54] <RhodiumToad> dtrebbien: TRUNCATE の小さな問題を除けば、シリアライゼーションの問題はすべて読み取り/書き込みクエリに関係しています

[15:03] <dtrebbien> RhodiumToad、johto、selenamarie、peerce: この会話のトランスクリプトを Stack Overflow に投稿してもよろしいですか?

[15:07] <selenamarie> dtrebbien: そうですね :)

[15:07] <dtrebbien> 誰の役に立つかわかりません。かもしれない。

[15:08] <selenamarie> dtrebbien: これに関する Kevin Grittner の講演のメモをここに投稿しました: http://www.chesnok.com/daily/2011/03/24/raw-notes-from-kevin-grittners-トークオンシー/

于 2011-10-09T19:33:29.700 に答える