web-dev-qa-db-ja.com

SQL + RESTスタックのtransaction-per.requestのよりスケーラブルな代替手段?

SQLデータベースを使用したWebプログラミングは初めてです。だから私の無知を許してください。

いくつかの最新のフレームワークを使用して、SQLデータベースを備えたRESTサーバーを作成しています。トランザクションは必要だと思う場合にのみ使用しています。しかし、開発中に、並列操作の土地を見つけました。デッドロックと一貫性のないデータが発生したため、SQLクエリにトランザクションを追加し始めました。

デッドロックのパラノイアを続ける私は、各RESTリクエストはSQLトランザクションと結合されている必要があるという考えに近づいています。

この方法はより安全ですが、データベースは要求が応答されるまでロックされます。さらにスケーラブルなソリューションを探しています。リクエストごとのトランザクションのパラダイムを使用する一部として、この問題を処理するための正しい方法は何かに関するヒントはありますか?

3
nkint

データベーストランザクションのポイントは、他のユーザーが同じデータベースに同時に書き込みを行っている場合でも、データベース内のいくつかの事実が同時に真であることを確認できるようにすることです。

銀行口座間で送金する正規の例を見てみましょう。システムは、ソースアカウントが存在し、十分な資金があり、宛先アカウントが存在し、借方と貸方の両方が発生するか、どちらも発生しないことを確認する必要があります。他のトランザクションが発生している間、おそらくこれら2つのアカウント間でさえ、これを保証する必要があります。システムは、関連するテーブルをロックすることにより、これを保証します。

どのロックが取得され、他の人の作業がどれだけ表示されるかは、トランザクション分離レベルによって制御されます。認識されている分離レベルはいくつかあり、各DBMSには実装固有のバリエーションがあります。ロックを恐れるべきではありません。これらは、データを保護し、ロールバックまたはシステムクラッシュが発生した場合の一貫性を確保するために存在します。

ロックの裏側は並行性です。これは、1つのデータベースに対して同時に発生する可能性のあるさまざまなタスクの数です。明らかに、1人のユーザーが取ったロックが多いほど、別のユーザーがブロックされる可能性が高くなります。これまで見てきたように、最終的にはデッドロックが発生する可能性があります。

デッドロックを回避するには、SQLステートメントをできるだけ近くで実行して、トランザクションを短くします(ただし、一貫性を確保するために必要以上に短くしないでください)。作業が完了したらすぐにトランザクションをコミットします。可能な場合は、表を特定の順序で読んでください。これにより、キューイング動作が促進され、デッドロックが減少します。適切に調整されたクエリと適切なインデックスがあることを確認してください。サーバーを増やすRAMワーキングセットがメモリにあり、クエリがより速く完了するようにします。DBトランザクションで少量のデータを処理します。理想的には、DBトランザクションごとに1つのビジネストランザクションです。デッドロックエラーコードをキャッチするようにアプリケーションをコーディングします。作業を再送信します。

かなり複雑なアプリケーションでは、最終的にデッドロックは避けられませんが、致命的である必要はありません。

2
Michael Green