ここから質問投稿すると、最大4000ポイント当たる!!!! >>

毎度お世話になっております。
SQLSERVER2000とACCESS2003を使用しています。

画面から抽出条件を入力し、画面表示ボタンを押すと
抽出条件をWHERE句にしたパススルークエリが実行され、
在庫、入庫予定、入庫実績、出荷実績を計算、
画面表示するプログラムを作りたいと考えています。

パススルークエリはSELECT文ですが、
サブクエリが多くあり、
FROM句にはたくさんのテーブルが入ります。

また、他端末で実績入力中でも
入力中の実績は反映されなくてもよいので、
実行、画面表示したいのです。


他の質問を検索して、
http://oshiete1.goo.ne.jp/qa3392465.html
SELECT文でもロックが発生することを知りました。
しかし、どのように対処するかは理解できませんでした。
ロックをおこすことなく他端末での実績入力も問題なく行われ、
画面表示もできるようにするにはどうすればよいのでしょうか

よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

誤解があるかな、と思うのは、


リンク先で話題になっているのは、OracleでFOR UPDATE句を付けてSELECTした場合であるということです。
FOR UPDATE句を付ければ、「更新前提に」SELECTしていることになるので更新ロック(に昇格可能なロック)がかかりますが、つけなければロックはかかりません。
SQL Serverの場合はテーブルヒントを付けないとこのようなSELECTはできないので、今回のパススルークエリに関しては「SELECTがロックしないようにする」というふうに考える必要はないと思います。

ただ、並行して行われている更新処理がレコードをロックした場合、SELECTは待ちがかかりますので、更新処理は極力短時間で行うようにする必要があると思います。
(分離レベルを変更してダーティリードすれば待ちませんが、さすがにお勧めしません)

この回答への補足

回答ありがとうございます。
今回もお世話になります。

回答いただいた内容について、また、ロックについて勉強しました。
テーブルヒント、分離レベルのところでかなり混乱していますが、
今の時点の私の理解を以下にまとめました。

パススルークエリをSQLSERVERで実行するときに共有ロックが
かかり、結果をACCESSに返すときにロックが外れる
(結果が画面に表示されるときにはもうロックが外れている)。
共有ロックは排他ロックをブロックするので、
SELECT文が実行されているとき、他端末での実績入力はWAITになる
(が、実行されている時間だけなのでとても短い時間になる)。
他端末が更新している場合はその排他ロックが外れるまでSELECT文はWAITになる(更新が完了するまでなのでわりと待たされる場合もある)。
どちらにしてもWAITになるだけなので、
SELECT文ではロックは起こらない。

このような理解にいたりましたが、正しいでしょうか。

よろしくお願いします。

補足日時:2008/07/22 19:01
    • good
    • 0

おおむね正しいです。


(超厳密な議論までは必要ないでしょう)
補足するとしたら、
・トランザクション分離レベルについては、通常は下から2番目のREAD COMMITTEDになっていて、COMMITしていない更新はSELECTでは読み取らないけれども、COMMITされれば即反映するので、今SELECTしたものが次SELECTしたものと同じという保証はないこと
・OracleとSQL Serverとではロックのメカニズムは同じではないこと
くらい認識していればいいかと思います。

この回答への補足

回答ありがとうございます。
頭の中がすっきりしました。

補足いただいた内容についても勉強していきたいと思います。

補足日時:2008/07/23 17:27
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qパススルークエリの使い方

Windows server 2003 + SQL server 2000の環境にあるDBがあります。
同じネットワーク上のWindows XP Pro + Access2000のPCからそのサーバのDBへデータをINSERTするのにはパススルークエリを使えという話になりました。
そのサーバへODBC接続の設定はできています。
パススルークエリの情報が乏しく、どのようにしたらよいのかちょっとわかりません。
どなたかご教授よろしくお願いいたします。

Aベストアンサー

#1です。やり方はわかったようですので、補足ですが、
パススルークエリは丸ごとSQL Serverにクエリを投げるので、
INSERT INTO (SQL Serverのテーブル) SELECT * FROM (Accessのテーブル)
みたいな使い方はできません。
基本的にはパラメータも渡すことができないので、実行の都度QueryDefのSQLを書き換えてExecuteするような使い方になるかと思います。

今回は1レコードだけということなので、特に問題はないと思いますが、複数レコードをINSERTするのだったら、
INSERT INTO TABLE VALUES ('A','B','C');
INSERT INTO TABLE VALUES ('D','E','F');
INSERT INTO TABLE VALUES ('G','H','I');

と並べるよりは
INSERT INTO TABLE
SELECT 'A','B','C'
UNION ALL SELECT 'D','E','F'
UNION ALL SELECT 'G','H','I'
とやると1ステートメントでINSERTできるので少し速いはずです。

#1です。やり方はわかったようですので、補足ですが、
パススルークエリは丸ごとSQL Serverにクエリを投げるので、
INSERT INTO (SQL Serverのテーブル) SELECT * FROM (Accessのテーブル)
みたいな使い方はできません。
基本的にはパラメータも渡すことができないので、実行の都度QueryDefのSQLを書き換えてExecuteするような使い方になるかと思います。

今回は1レコードだけということなので、特に問題はないと思いますが、複数レコードをINSERTするのだったら、
INSERT INTO TABLE VALUES ('A','B','C...続きを読む

QAccessのRefresh・Requery・Repaintの違い

Requeryはもう一度ソースレコード(テーブル)を読み込むようです。このとき、テーブルの先頭レコードに移動してしまいます。
Refreshは最新のレコード(テーブル)を再表示するような気がします。レコードの移動は起こらない気がします。
Repaintは、VBAでキャプションなどを変更したとき使っています。
でも、よくわかっていません。
どんなときにどんなメソッドを使えばいいのでしょうか?
詳しい方、よろしくお願いいたします。

Aベストアンサー

たびたびすみません。
調べてたらこんなのがでてきました。
http://www.nurs.or.jp/~ppoy/access/access/acF007.html

参考URL:http://www.nurs.or.jp/~ppoy/access/access/acF007.html

QDoEvents関数って何?

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そこで「EXCEL VBA パーフェクトマスター」という本を見たら

for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
DoEvents
next i
unload userform1
と入力すれば解決することがわかりました。

しかし「DoEvents」についてあまり詳しく書いていなかったのでDoEvents関数をヘルプで見ると、
「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」

と書いてあるのですが正直、書いてあることがよくわかりません。

どなたかDoEvents関数について、
もう少しわかりやすく教えていただけませんか。
それから、最初に書いたコードで実行すると
ユーザーフォームの背景が真っ白になってしまう原因も
教えていただけませんか?

よろしくお願いいたします。

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そ...続きを読む

Aベストアンサー

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
    DoEvents
    Cells(i,1) = ""
  Next i
End Sub

Private Sub CommandButton2_Click()
  MsgBox "hoge"
End Sub

っていうフォームのコードがあった場合、
DoEvents を入れることによって、ループ中にユーザーがCommandButton2 を押すことによって CommandButton2 のクリック イベントも動いちゃいます。
CommandButton1 のクリック イベントではループの前に
CommandButton1.Enabled = False
CommandButton2.Enabled = False
を書いてフォーム上の CommandButton を無効にしておき、ループが終わったら
CommandButton1.Enabled = True
CommandButton2.Enabled = True
と書いて CommandButton を有効に戻してください。

これを工夫すれば、CommandButton2 で CommandButton1 のループを途中キャンセルする処理もすることができます。

Private Canceled As Boolean

Private Sub CommandButton1_Click()

  CommandButton2.Enabled = False

  Dim i As Long
  For i = 1 To 50000
    DoEvents

    If Canceled = True Then
      MsgBox "キャンセルしました"
      Exit Sub
    End If

    Cells(i, 1).Value = ""
  Next i
End Sub

Private CommandButton2_Click()
  Canceled = True
End Sub



コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。
コピペするなら行頭の全角スペースを半角スペースに直してください。

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
...続きを読む

QAccessの画面更新を一時的に停止する方法。

こんにちは。
Accessの画面更新を一時的に停止する方法を捜しています。
ExcelのScreenUpdatingと同様な機能です。

VBAでの更新処理時に画面がチラチラと動くのを防止したいと思っています。
(Ver:Access2000)
ご存知の方宜しくお願い致します。

Aベストアンサー

Application.Echo False '画面の描画を止める

・・・処理を実行する・・・

Application.Echo True '画面の描画を行う

QAccessのDAO.ExecuteとDoCmd.RunSqlの違いについて

アクションクエリを実行する際、表題の2つを検討しています。
最重要な違いに同期と非同期であることをネットで検索して分かりました。
非同期だとどのような問題が発生するのか具体的に教えて頂けると助かります><

Aベストアンサー

DoCmd.RunSQL ですが、「非同期」であると幾つかのHPで見かけましたが、実際試してみると「同期」実行している感じです(Access2000で実験)。

実際「非同期」なんでしょうか?
オフィシャルなサイトに「非同期である」と言う記述はありますか?

------------検証プログラム------------
Sub local_test()
 Dim SQL(4) As String
 Dim t As Double

 SQL(1) = "UPDATE T1 SET Data = '0';"
 SQL(2) = "UPDATE T1 SET Data = '1';"
 
 SQL(3) = "UPDATE T2 SET Data = '0';"
 SQL(4) = "UPDATE T2 SET Data = '1';"
 
 '初期化
 CurrentDb.Execute SQL(1)
 CurrentDb.Execute SQL(3)

 'DoCmd.RunSQL テスト--------------------------------------------
 DoCmd.SetWarnings False
 t = Timer()
 DoCmd.RunSQL SQL(2)
 Debug.Print "DoCmd.RunSQL " & Format(Timer() - t, "0.00000")
 DoCmd.SetWarnings True

 'DAO.Execute テスト--------------------------------------------
 t = Timer()
 CurrentDb.Execute SQL(4)
 Debug.Print "CurrentDb.Execute " & Format(Timer() - t, "0.00000")
End Sub
---------------------------------------------------------

T1 T2 とも、3万件程度のテストデータが入っています。
DoCmd.RunSQL の方も処理が終わるまで返ってきません(同期実行では?)

DoCmd.RunSQL は SetWarnings を設定しないと、確認メッセージが出でます。
DoCmd.RunSQL が同期実行だとすると、これ以外に大きな違いは無いのかも知れませんね。


##########################################################
今度はADOを使って無理やり非同期実験
別のmdbにファイルにADOでアクセスしています。

------------検証プログラム------------
Sub ado_test()
 Dim cnn(2) As New ADODB.Connection
 Dim SQL(6) As String
 Dim dbName As String
 Dim t As Double

 dbName = "c:\temp\db1.mdb"

 SQL(1) = "UPDATE T1 SET Data = '0';"
 SQL(2) = "UPDATE T1 SET Data = '1';"
 SQL(3) = "UPDATE T1 SET Data = '2' WHERE Data = '1';"
 
 SQL(4) = "UPDATE T2 SET Data = '0';"
 SQL(5) = "UPDATE T2 SET Data = '1';"
 SQL(6) = "UPDATE T2 SET Data = '2' WHERE Data = '1';"
 
 cnn(1).Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & dbName & ";"
 cnn(2).Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & dbName & ";"
 
'初期化
 cnn(1).Execute SQL(1)
 cnn(1).Execute SQL(4)

'同期実行テスト--------------------------------------------
 t = Timer()
 cnn(1).Execute SQL(2)
 cnn(1).Execute SQL(3)
 Debug.Print "同期実行  " & Format(Timer() - t, "0.00000")

'非同期実行テスト--------------------------------------------
 
 t = Timer()
 cnn(1).Execute SQL(5), , adAsyncExecute
 cnn(2).Execute SQL(6), , adAsyncExecute
 Debug.Print "非同期実行 " & Format(Timer() - t, "0.00000")
End Sub
---------------------------------------------------------
非同期の方が明らかに速いです。(処理を待たずに返ってくるので)
非同期の方は正しく更新できてません。

この検証プログラムが正しいのか?、あまり自信はありません(^^;
参考程度にして下さい。

##########################################################
補足
DAOかADOか?

http://www.naboki.net/access/heaven/heaven_14.html
http://homepage2.nifty.com/inform/vbdb/daoado.htm

DoCmd.RunSQL ですが、「非同期」であると幾つかのHPで見かけましたが、実際試してみると「同期」実行している感じです(Access2000で実験)。

実際「非同期」なんでしょうか?
オフィシャルなサイトに「非同期である」と言う記述はありますか?

------------検証プログラム------------
Sub local_test()
 Dim SQL(4) As String
 Dim t As Double

 SQL(1) = "UPDATE T1 SET Data = '0';"
 SQL(2) = "UPDATE T1 SET Data = '1';"
 
 SQL(3) = "UPDATE T2 SET Data = '0';"
 SQL(4) = "UPD...続きを読む

Qクエリとパススルークエリを作る時の考え方について

現在、リンクテーブルに対し、以下のクエリを作成しております。

1.Q_在庫:在庫を品番で集計する。
 [結果]
  品番 在庫
   A  100
   B   20

2.Q_受注:受注データの残数を集計する。
 [結果]
  ID 品番 納期   予定数 合計数
  1  A  20080625  10   10
  2  A  20080626  50   60
  3  A  20080627  100  160

3.Q_可否:Q_在庫とQ_受注を品番でリレーションし、在庫行を付加し、
在庫が合計数を上回っていれば"○"を表示する。
 [結果]
可否 ID 品番 納期   予定数 合計数 在庫
○  1  A  20080625  10   10   100
○  2  A  20080626  50   60   100
×  3  A  20080627  100  160   100

このとき、Q_可否を実行すると、20秒くらいかかってしまい、
パススルークエリのほうがよいのかな?と考えています。

ただ、私以外の人が後から変更などする場合、
長いSQL文はわかりづらいだろうとも考えます。

どちらかを犠牲にするしかないのでしょうか。
もっと良い方法があるのでしょうか。

漠然とした質問で申し訳ありませんが、よろしくお願いします。

現在、リンクテーブルに対し、以下のクエリを作成しております。

1.Q_在庫:在庫を品番で集計する。
 [結果]
  品番 在庫
   A  100
   B   20

2.Q_受注:受注データの残数を集計する。
 [結果]
  ID 品番 納期   予定数 合計数
  1  A  20080625  10   10
  2  A  20080626  50   60
  3  A  20080627  100  160

3.Q_可否:Q_在庫とQ_受注を品番でリレーションし、在庫行を付加し、
在庫が合計数を上回っていれば"○"を表示する。
 ...続きを読む

Aベストアンサー

Q、棚卸しの手法。
A、棚卸一時テーブルを一気に作成。

これで、サーバーの関連テーブルとのアクセスは全て終了。
で、関連テーブルは、他のクライアントに開放できます。
で、参照や印刷では棚卸一時テーブルを利用。

Access のリンクテーブルはその都度に全てのデータを取り込んで処理。
そのデータを参照する都度に再び全てのデータを取り込んで処理。
これを二重、三重に仕掛ければ処理が遅くなるのは必定。

最初から3を作成しても1万件でも1、2秒かと思います。
で、表示は時間計測不能かとも・・・。

Q[Access]帳票フォームにて連続する非連結コントロールに個々の値を入れるには

Accessにおいて。
帳票フォームの"詳細"に非連結のコントロール(例:テキストボックス)を配置し、それぞれ別々の値を持たせることは可能なのでしょうか?

例えば。
VBAにおいて、カレントレコードのAという値とBという値を計算し、その値を非連結のテキストボックスに挿入したとします。
単票フォームであれば、問題なくテキストボックスには計算後の値が表示されるわけですが……
帳票フォームの場合では、"規定値"に計算式を入れたときと同様、先頭の値と同じものが連続するテキストボックスに表示されてしまいます。
これを回避し、計算後のデータを連続するテキストボックスにそれぞれの値として表示させるには、どのようにすればよいのでしょうか?

もちろん、連結させたコントロールを使用すれば、問題はないのですが……
状況によっては、これが行えた方が便利かと思い、質問させていただきます。

「帳票フォームでは不可能である」といった回答でもかまいません。
どうぞよろしくお願いいたします。

Aベストアンサー

非連結のTEXTBOXの値は一つなので、帳票フォーム上で別々の値を持つような設計は出来ません。
新たに暫定的なテーブルを作成して、元になるテーブルとリレーションさせる方法でないと難しいと思います。

QSQL Server時間切れについて

初めまして。SQL初心者です。
あるシステムにおいて、SQLサーバが無応答?になり、システムがダウンしてしまい、困っています。

Windows2000Server、SQL Server2000、VB6を用いてDBに定期的にRead&Write、及び各種のデータ表示を行っています。
ADOを使用して、接続や各コマンドを実行しているのですが、ごくたまに以下のエラーが出てしまいます。
Code:-2147217871,Description:時間切れになりました。Source:Microsoft OLE DB Provider for SQL Server,SQL State:HYT00,NativeError:0
過去ログや他サイトを調べた結果、コネクションのCommandTimeoutの秒数を延長させる、とあったので60秒に変更しました。
が、不定期(大体1週間~10日前後で夜中や朝方などにもあり)にこのエラーが出てしまい、約1時間~1時間半もダウンしています(この間のエラーをOn Errorではじいてログファイルに保存しています)。
毎分必ず実行しているストアド(20装置分のデータをUPDATEするので1分に20回実行する)があるのですが、必ずと言っていいほどこのストアド実行中に落ちています。
このストアドに5~6個のパラメータを渡し、複数のテーブルに対してUPDATE処理を行っています。
正常に動作している時は、数日間全く問題無いので、ストアドやVBのコードに間違いは無いと思います。

そこで、SQL Serverの設定等を見直したところ、1つ気になったところが。データベースファイル
\Microsoft SQL Server\MSSQL\Data\aaa.MDF
のサイズが14Gになっていました・・・。
このファイルにアクセスする時にSQL Serverで高負荷になってしまい、無応答のような状態になってしまうのでは?と思っていますがどうでしょう?

不定期に発生し、かつ再現性が無く、原因が掴めずに本当に困っています。
先輩方、何でも良いのでアドバイスをお願い致します。

初めまして。SQL初心者です。
あるシステムにおいて、SQLサーバが無応答?になり、システムがダウンしてしまい、困っています。

Windows2000Server、SQL Server2000、VB6を用いてDBに定期的にRead&Write、及び各種のデータ表示を行っています。
ADOを使用して、接続や各コマンドを実行しているのですが、ごくたまに以下のエラーが出てしまいます。
Code:-2147217871,Description:時間切れになりました。Source:Microsoft OLE DB Provider for SQL Server,SQL State:HYT00,NativeError:0
過去ログや他サイ...続きを読む

Aベストアンサー

14Gですか・・・大きいですね。
データの構造がどうなのか解らないので、
容量的に妥当かどうかはわかりませんが、
一度インデックスの再構築と圧縮を掛けてはどうでしょうか


CREATE PROCEDURE SP_COMPRESS AS

DECLARE @name varchar(30)

DECLARE tnames_cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE type = 'U'
OPEN tnames_cursor

FETCH NEXT FROM tnames_cursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
PRINT @name + 'のDBREINDEX...'
EXEC ('DBCC DBREINDEX ('+ @name + ')' )
FETCH NEXT FROM tnames_cursor INTO @name
END
DEALLOCATE tnames_cursor

dbcc SHRINKFILE("SampleDb_Log",1)
DBCC SHRINKDATABASE("SampleDb",1)
GO


データベース名は自分の環境に合わせてください。
また、バックアップは必ず取っておいてください。
14Gもあれば結構時間がかかると思いますが・・・

とりあえず参考程度に・・・

14Gですか・・・大きいですね。
データの構造がどうなのか解らないので、
容量的に妥当かどうかはわかりませんが、
一度インデックスの再構築と圧縮を掛けてはどうでしょうか


CREATE PROCEDURE SP_COMPRESS AS

DECLARE @name varchar(30)

DECLARE tnames_cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE type = 'U'
OPEN tnames_cursor

FETCH NEXT FROM tnames_cursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
PRINT @name + 'のDBREINDEX...'
EXEC ('DBCC DBREINDEX (...続きを読む

QアクセスVBAのMe!と[ ]

基本的なことですみません。

アクセスのイベントプロシージャで、Me!ってありますけど、これはどういう意味なんでしょうか?

また、Me!の後に、Me!.~~と書く場合と、Me!.[~~]と書く場合がありますが、どこが違うのでしょうか?

Aベストアンサー

>プロシージャ内で[]を使う場合は、そのフォーム外のオブジェクトを使う場合と考えてよろしいでしょうか?
別のオブジェクトを使う場合だけではありません。
Hensu = Me![Text1]のようにHensuという変数に自身のTest1の値を代入する場合のように。
[]で括られているのがオブジェクト名やコントロール名だよという事。
クエリの抽出条件に存在しない[?]とすれば?というコントロール等が参照できないので?というダイアログが表示されるように?というオブジェクトやコントロールは何?と聞いてくるように。
>フォーム内のオブジェクトの場合はあくまでMe!で良いのでしょうか
Forms.[フォーム名]![コントロール名]やForms![フォーム名]![コントロール名]が構文。
アクティブなフォームが自分自身ならForms![フォーム名]の変わりにMeでもOKですという事。

と言う解釈の方が良いと思います。

Q同じSELECT文同士でのデッドロックが発生

ORACLE10Gを使用したアプリ開発中です。

アプリ中、1テーブルに対して全く同じ条件で
複数レコードを悲観的ロック(for update)しながら取得し、
項目を更新するSQLを発行します。

単発では問題なかったのですが、処理時間の関係で
パラレルで実行された場合にデッドロックを検出することがあります。

ORACLEのudumpの中を確認すると全く同じSELECTのSQL同士で
デッドロックが発生したと表示されています。

こういった場合、どういう原因が考えられるでしょうか?
(同じ条件による悲観的ロックであれば多重実行でも
 処理待ちをするだけだと思っているのですが・・・)

よろしくお願いします。

Aベストアンサー

>2つの処理がロックしてしまう、というように聞こえますが
>こういうことはあるんでしょうか?
あるんです。Aのプロセスも、Bのプロセスも「誰もロックしてない」って思ってますから。
Aがロックを掛けた直後に、Bは「さっき調べた時は誰もロックしてなかったから、ロックしよう」と「上書きロック」をしてしまいます。

通常は1と3の間に2が割り込まず、2が後回しになる為、以下のようにAもBも正常終了します。
1.Aがレコードのロック状態を検査。ロック無しと判定
3.Aがレコードをロック
2.Bがレコードのロック状態を検査。ロック有りと判定
4.Bはレコードのロックが解除されるまで待ち合わせ
(以下略)

デットロックの直接の原因は「間に割り込みが入らず一連の動作として処理しなければならない、ロック状態の検査とロック設定の間に、別プロセスが割り込むため」です。

こういうケースは、データベースがサーバー上にあり、アクセスがネットを介して行われる場合で、2つのプロセスが同時に同じ処理を行った際に多発します。

回避には、独自にセマフォ変数やミューテックス変数を用意するなどして「データベースのロック機能以外を使って」排他制御が必要です。

>2つの処理がロックしてしまう、というように聞こえますが
>こういうことはあるんでしょうか?
あるんです。Aのプロセスも、Bのプロセスも「誰もロックしてない」って思ってますから。
Aがロックを掛けた直後に、Bは「さっき調べた時は誰もロックしてなかったから、ロックしよう」と「上書きロック」をしてしまいます。

通常は1と3の間に2が割り込まず、2が後回しになる為、以下のようにAもBも正常終了します。
1.Aがレコードのロック状態を検査。ロック無しと判定
3.Aがレコードをロ...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング