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