libpqxx トランザクションのシリアル化とその結果
-
21-12-2019 - |
質問
私の実装では、特定の書き込みは別の干渉の可能性なしに一括して実行する必要があります。
私は行ってきました 言った このようにして 2 つの競合するトランザクションが最初のトランザクションで 2 番目のトランザクションをブロックし、最初のトランザクションが完了した後に 2 番目のトランザクションが完了する場合と完了しない場合があります。
これを確認する文書を投稿してください。また、最初のトランザクションがブロックされている場合、2 番目のトランザクションは正確にどうなるのでしょうか?キューに入れられるのか、失敗するのか、それともその組み合わせなのか?
これを確認できない場合は、このトランザクションのトランザクション分離レベルを次のように設定する必要があります。 SERIALIZABLE
?もしそうなら、libpqxx プリペアドステートメントを使用してどのように実行できますか?
トランザクションがシリアル化されている場合、2 番目のトランザクションは失敗しますか、それとも最初のトランザクションが完了するまでキューに入れられますか?
どちらかが失敗した場合、libpqxx を使用してどのように検出できますか?
解決
同時実行の影響を決定的に防ぐ唯一の方法は、 LOCK TABLE ... IN ACCESS EXCLUSIVE MODE
変更する各テーブル。
これは、実際には一度に 1 つのことしか行っていないことを意味します。また、常に同じ順序でロックを取得しないと、デッドロックに関する興味深い問題が発生します。
したがって、通常、行う必要があるのは、実行したい操作が正確に何であり、それらがどのように相互作用するかを理解することです。許容できる同時実行効果と、許容できない同時実行効果を防ぐ方法を決定します。
この質問は現状では範囲が広すぎて、有効に答えることができません。
オプションには次のものが含まれます。
テーブルを排他的にロックします。(これは 唯一の方法 現在、PostgreSQL で同時実行の問題を発生させずに複数行の更新/挿入を実行するには)。ロックのアップグレードとロック順序に関連するデッドロックに注意してください。
の適切な使用
SERIALIZABLE
分離 - ただし、トランザクション中に行ったことの記録を保持し、TX が中止された場合に再試行できる必要があることを覚えておいてください。慎重な行レベルのロック -
SELECT ... FOR UPDATE
,SELECT ... FOR SHARE
.「オプティミスティック ロック」/オプティミスティック同時実行制御 (該当する場合)
クエリを同時操作に適した方法で作成します。たとえば、読み取り、変更、書き込みサイクルをインプレース更新に置き換えます。