4

これについてここで質問を見ましたが、それは古いので、解決策が存在する場合はもう一度質問します.

私の問題はこれです。選択したいデータベース テーブルがありますが、選択した行をロックしたいと考えています。この理由は、同じ行を選択したい別のプロセスを実行している可能性があり、これを防ぎたいからです。

同じことをしている 2 つのプロセスがあるとします。選択を実行し、データの処理を開始します。その後、数秒後に次のプロセスが来て選択を行いますが、行がロックされていないため、同じレコードを取得して処理を開始します。もちろん、これは悪い状況です。Oracleでは、SELECT FOR UPDATEを使用できます。これにより、行のロックが解除され、2番目のプロセスで行が使用されるのを防ぐことができます。これは SQL Server 2008 でどのように実現できますか?

標準の sql ステートメントしか使用できないことを付け加えておきます。プロシージャ、関数などにアクセスできません。簡単なステートメントで実行する必要があります。それは長い話であり、私の手を離れてしまった設計上の考慮事項です。ソリューションは、テーブルに格納し、後で取得して、特にコマンド オブジェクトに割り当てられた C# の ADO オブジェクトを介して実行できる必要があります。

このステートメントにロックを適用するにはどうすればよいですか?

SELECT * 
FROM 
  (SELECT TOP (20) * 
   FROM [TMA_NOT_TO_ENTITY_QUEUE]  
   WHERE [TMA_NOT_TO_ENTITY_QUEUE].[STATE_ID] = 2 
   ORDER BY TMA_NOT_TO_ENTITY_QUEUE.ID) a
4

4 に答える 4

9

いわゆるテーブル ヒントのいずれかを使用する必要があります。

更新ロックは、他のプロセスが問題の行を更新または削除しようとするのを防ぎますが、読み取りアクセスは妨げません。

    SELECT TOP (20) * 
    FROM [TMA_NOT_TO_ENTITY_QUEUE] WITH (UPDLOCK)
    WHERE [TMA_NOT_TO_ENTITY_QUEUE].[STATE_ID] = 2 
    ORDER BY TMA_NOT_TO_ENTITY_QUEUE.ID

排他ロックもありますが、基本的には更新ロックで十分です。更新ロックを使用して行を選択すると、トランザクションが終了するまで、それらの行は更新と書き込みから「保護」されます。

于 2012-08-14T10:36:32.257 に答える
3

ロックによって、2 番目のプロセスをどうしたいですか? 最初の処理が完了するまで待機させたい場合は、トランザクション分離レベルを使用して完全に行うことができます。

この小さなテストを実行してみてください。

SSMS で 2 つの新しいクエリを開き (これからは A と B と呼びましょう)、A で次のような単純なテーブルを作成します。

create table transTest(id int)
insert into transTest values(1)

次に、次の操作を行います。

select * from transTest両方で行います。値 1 が表示されます

実行時:

set transaction isolation level read committed

B 実行時:

begin transaction
insert into transTest values(2)

実行時:

select * from transTest

Bのトランザクションによってロックされているため、クエリが終了しないことがわかります

B 実行時:

commit transaction

A に戻ると、クエリが終了したことがわかります

A で set transaction isolation level read uncommitted を使用してテストを繰り返します。クエリがトランザクションによってロックされないことがわかります。

于 2012-08-14T09:37:41.833 に答える
2

プロセスをトランザクションでラップし、トランザクション分離レベルを適切に設定する必要があります (つまり、シリアライズ可能)。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
     UPDATE yourtable...
     -- process 1
COMMIT TRAN

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
     UPDATE yourtable...
    -- process 2
COMMIT TRAN

この動作は、太古の昔から SQL Server にありました。

他のトランザクション分離レベルが利用可能です。

于 2012-08-14T09:24:15.940 に答える
0

SQL Server と Oracle のロック メカニズムは完全に異なります (動作が逆であっても)。コードにトランザクションレベルの制御要素を含めると、「データベースにとらわれない」ことはありませんが、合理的な複雑さのデータベースコードは「データベースにとらわれない」ことはありません。「プレーン SQL」のみを使用する必要がある場合は、SQL92 仕様内にとどまり、「link-to-SQL」を使用せずにアプリケーション側でトランザクションを制御しますが、効果的な (データベース固有の) ソリューションを作成する能力が制限されます。

于 2016-09-22T18:17:19.927 に答える