ロックしたいテーブルを持つSQLデータベースがあります。EntityFrameworkを使用しています。基本的に、それぞれがデータベースに同時に書き込みたいプロセスがいくつかあります。それらのそれぞれは、いくつかのテーブルの行を更新したいと考えています。ただし、同時にこれを実行できるのはそのうちの1つだけです。
誰かが新しい行を配置したり行を更新したりできないようにするなど、テーブル全体をロックする方法はありますか?
ありがとう、クリスチャン
ロックしたいテーブルを持つSQLデータベースがあります。EntityFrameworkを使用しています。基本的に、それぞれがデータベースに同時に書き込みたいプロセスがいくつかあります。それらのそれぞれは、いくつかのテーブルの行を更新したいと考えています。ただし、同時にこれを実行できるのはそのうちの1つだけです。
誰かが新しい行を配置したり行を更新したりできないようにするなど、テーブル全体をロックする方法はありますか?
ありがとう、クリスチャン
なぜこれが必要なのかは私にはわかりませんが、テーブル全体を本当にロックしたい場合は、次のことができます。
ここから適応した例:
ALTER INDEX [MyIndexName] ON [dbo].[MyTableName] SET ( ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF)
注:これは、アプリケーションがこれらのテーブルのみを「所有」していることを前提としています。これを適用して他のアプリを壊したくないでしょう。
ここから適応した例:
TransactionOptions topt = new TransactionOptions();
topt.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using (var tran = new TransactionScope(TransactionScopeOption.Required, topt)) {
//do stuff
}
簡単な説明から、この問題を解決するためにテーブルロックが本当に必要なものであるかどうかは疑わしいです。よりスケーラブルな一般的なソリューションには、次のものがあります。
1)最初のステートメントとして対象のレコードを読み取るか更新するシリアル化可能なトランザクションを作成します。すべての更新は、このパターンに従おうとする必要があります。
2)(1)のようなread_committedトランザクションを作成しますが、同時実行例外での再読み取り/再試行機能を含めます。
テーブルをロックする必要があることはめったにありません。手動で決定されたIDフィールド値に何らかの計算が含まれ、別のセッションと衝突する可能性がある場合に必要になる場合があります。
その呼び出しだけで、トランザクションを作成し、テーブルを最初にロックすることができます。ロックは、読み取りと書き込みを防ぐために「X」(排他的)にすることも、書き込みだけを防ぐために非排他的にすることもできます。この回答はSPを使用しています。
別の方法として、アプリケーションロックを使用することもできます。