web-dev-qa-db-ja.com

UPDLOCKとFOR UPDATEの違い

次のコードが与えられた:

Set conn = CreateObject("ADODB.Connection")
Set RS = CreateObject("ADODB.Recordset")
conn.BeginTrans
...
//This is the line it is about
RS.Open "SELECT a,b FROM c FOR UPDATE", conn, adOpenDynamic, adLockPessimistic
...
RS.Close
conn.CommitTrans
conn.Close

私が使用するときの違いは何ですか:

RS.Open "SELECT a,b FROM c (UPDLOCK)", conn, adOpenDynamic, adLockPessimistic

更新:

現在、FOR UPDATEを使用していますが、テーブルがロックされていないようです。 SQLプロファイラーはこれを示しています。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

declare @p1 int  set @p1=NULL  declare @p3 int  set @p3=229378  declare @p4 int  set @p4=163842  declare @p5 int  set @p5=NULL  exec sp_cursoropen @p1 output,N'SELECT a,b FROM c FOR UPDATE',@p3 output,@p4 output,@p5 output  select @p1, @p3, @p4, @p5 

UPDATE c SET a = a + 1 WHERE b = 'Value' 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

IF @@TRANCOUNT > 0 COMMIT TRAN 

使用する更新ステートメント:

SQL = "UPDATE c SET a = a + 1 WHERE b= 'Value'"
4
amaters

FOR UPDATEは、通常のSQLステートメントでは有効なSQL Server構文ではありません。 cursor を作成するときに使用されます。

しかし、おそらくADO with CursorLocationadUseServerを使用しているので、ADOは- sp_cursoropen は、カーソルに使用される構文を受け入れます。

SQL Serverのデフォルトの動作では、カーソルを更新できるため、列リストも指定しない限り、for updateを指定しても何も起こりません。

カーソルでupdlockクエリヒントを指定すると、トランザクションで実行している場合にのみ機能します。 updlockを使用すると、ロックはfetch next from ...を実行したときに配置され、updlockを使用しない場合は、update ... where current ofを実行したときにロックが配置されます。

したがって、あなたのケースでは、トランザクション中でupdlockを使用すると、データをフェッチするときにロックがかかります。 updlockを使用しない場合、トランザクションでは、データを更新するときにロックをかけます。トランザクションが存在しない場合、2つの間に違いはなく、それらのいずれも使用できません。

6
Mikael Eriksson

一般的に-違いはありません。 Oracle、DB2、MySqlはFOR UPDATEを使用しますが、SQL ServerではUPDLOCKクエリを使用できます。結果は同じです。選択した行をブロックして、テーブルの更新を行います。しかし、実装は少し異なります。 SQL Serverでは、行レベルだけでなく、ページレベルまたはテーブルレベルでもロックが実行されることがあります。そしてメイン-それは新しい選択の結果をブロックします(そのため、時々デッドロックで実際の問題が発生する可能性があります)。 Oracleは行レベルでのみロックを行い、それらは選択可能です。私の知る限り、これらのサーバー機能を使用することはベストプラクティスではないので、使用しないようにしてください。

3
Alex