2016-10-01 11 views
0

テーブル行(1〜100行)の値を常に更新するアプリケーションがあります。 このデータの整合性が重要なので、私はこれらの行を読み込んで更新する関数でトランザクションに対してSERIALIZABLEロックを使用しています。SERIALIZABLEロックの下にある可能性のあるデータのSELECT

今私の質問は、トランザクションで現在使用されている行に単純な読み取り専用SELECT(ロックなし)を実行すると、おそらくDEADLOCK例外が発生する可能性がありますか? これは、単純なSELECTの場合でもDEADLOCKの場合にはまだ再試行の仕組みが必要であることを意味しますか?

+0

私が本当に必要とするのは、最後にコミットされたレコードの状態を返すことです。基本的には、完全性については気にしません。 – NullReference

+0

それはちょうどときどきです。たとえば、ある行の状態を更新する関数があり、呼び出されたときに他のトランザクションがそのレコードを読み取ったり更新したりしないようにします。今私は現在のステータスを照会する必要があり、私はまったくデータの整合性を気にしません。 – NullReference

+0

MSSQLデータベース。 – NullReference

答えて

2

今、私は(コメントから)あなたの特定のビジネスシナリオが何であるかを知っていることは、ここであなたは、これがあることをシリアライズ可能分離に

CREATE PROCEDURE [dbo].[updateUserState] (@UserID int) 
AS 
BEGIN 
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 
    BEGIN TRANSACTION 

     SELECT [State] 
     FROM [dbo].[UserState] WITH (UPDLOCK) 
     WHERE [UserID] = @UserID; 

     IF ([State] = 'logged out') 
     BEGIN 
      UPDATE [us] 
      SET [State] = 'logged in' 
      FROM [dbo].[UserState] AS [us] 
      WHERE [UserID] = @UserID; 
     END 

    COMMIT TRANSACTION 
END 

注意を実装することなく、あなたが提案しているもののような何かをしたい方法です簡略化されていますが、主なアイデアを提示しますSELECTステートメントのUPDLOCKヒントが鍵です。 「私は更新を行うつもりでデータを選択しようとしています(直後です)、トランザクションが終了するまでそれを保持してください」というメッセージが表示されます。あなたの例では、T2が来て、T1がまだ動いているならば、T2は更新ロックを得ることができないので、T1が完了するまで待つでしょう。また、トランザクション分離レベルを明示的に設定することは完全性のためのものであり、 READ COMMITTEDがSQL Serverの既定値です。

+0

はい、あなたは完全に正しいキーです。いくつかの研究をした後、私は今それを実現します。残っている唯一のことは、Entity Frameworkの更新ロックでSELECTを実行する方法を見つけることです。 – NullReference

+0

EFでストアドプロシージャを使用できます。このレベルの制御が必要なときは、良いユースケースです。 –

+0

正直言って私はそれらを避けることを好むので、おそらく通常のSQL文を使ってデータを取得します。それでも、その奇妙なEFは、これがかなり標準的なことであるように、この機能を欠いています。 – NullReference

関連する問題