トップページtech
33コメント18KB

VBマガジンSQLServer特集にて

■ このスレッドは過去ログ倉庫に格納されています
00011NGNG
BeginTrans から CommitTrans の間のSQL文は別の処理が入ら
ないので整合性が保たれるというような事が書いてあるが、以下
のような事をすると不具合が起こりますが、VBMに書いてある事
が間違っているのでしょうか?それとも他になにかしないといけな
いのでしょうか?

Private Sub Command1_Click()
Dim CN As ADODB.Connection
Dim RS As ADODB.Recordset
Dim 在庫数 As Currency

Set CN = New ADODB.Connection
CN.Open OpenStr
CN.BeginTrans
Set RS = CN.Execute("SELECT 在庫数 FROM ZAIKO WHERE 商品ID=1")
在庫数 = RS("在庫数") - 1
RS.Close
Set RS = Nothing
Stop 'ここで別 PC の Access で在庫数変更
CN.Execute ("UPDATE ZAIKO SET 在庫数=" & 在庫数 & " WHERE 商品ID=1")
CN.CommitTrans
CN.Close
Set CN = Nothing
End Sub
0002デフォルトの名無しさんNGNG
ここじゃなくてVBマガジンに言えよ
っていうかいつでも雑誌が正しいと思ってたら
泣くのは君だよ
0003デフォルトの名無しさんNGNG
>BeginTrans から CommitTrans の間のSQL文は別の処理が入ら
>ない
普通ディスクアクセスがあると、他のタスク・プロセスに
切り替わるから、なんかの間違いじゃないの
0004デフォルトの名無しさんNGNG
>>1
あなたのトランザクションの理解が間違っている。
0005デフォルトの名無しさんNGNG
>>1
 >>4のことをもう少しわかりやすく言うと
「トランザクションとロックは違う」

 でも、これが本当に本に掲載されていたサンプルだとすると、
その出版社の本買えなくなるなぁ…
00061NGNG
>>5
私も普段はこういう使い方はしてませんが、1で書いたような使いかた
が出来るのなら便利だと思い試した所、不具合が起るので疑問に思い
皆さんに意見を求めてみました。
やはりこの方法は無理があるようですね。むぅー
0007デフォルトの名無しさんNGNG
Q.1.トランザクションとは何か?
A.4.記憶は確かですか?
A.5.ロックを唱えなされ。
Q.6.ではトランザクション制御を行うにはどうすればいいか?
A.4.理解が違っている
6.方法に無理がある
 7.1=6はちょっとおかしい
0008cafeNGNG
1の気持ちは分かるよ。そう錯覚させるような記事が多いから。
同期制御と排他制御は別物なんだよ。
00091NGNG
VBMを見てない人もいるようなので、もう少し詳しく書きます。
@顧客の確認
A在庫の確認
B在庫を減らす
C発注情報の書き込み
以上の処理の間に別のユーザーが入ると在庫不足になったりするので
トランザクション処理をして別のユーザーが入らないようにしている。
と書いてあったのでトランザクション処理で別のユーザーが入らない
ならロックする必要ないなーと思い実験してみたら駄目だったので
疑問に思いました。
0010デフォルトの名無しさんNGNG
>>9
しつこいね。
それから丸数字やめて。
0011デフォルトの名無しさんNGNG
1はもっと勉強せよ。
それから、3はタダの知ったかなので無視すれ。タスクスイッチと
トランザクションには関連は無い。
0012デフォルトの名無しさんNGNG
ほーー
トランザクション中にタスクスイッチが起こることはないとな
それでは、VBmと同じ説だな
00131NGNG
しつこくてすいませんでした。
私の周りに詳しい人がいないので、本やネットが頼り
なものでスレを立ててしまいました。
助言して頂いた方ありがとうございました。
001411NGNG
>>12
誰もトランザクション中にタスクスイッチが起こらないとは書いていないが。
トランザクション中にタスクスイッチが起ころうが起こるまいが、
トランザクションには関連が無い、と書いているのだが。

タスクスイッチがトランザクションと関連があるというのであれば、
説明をしてください。
001512NGNG
嫌だ

トランザクションとタスクスイッチは基本的になにの関係もない
タスクスイッチはレコードロックと関係がある。
001612NGNG
プププ
001714NGNG
>>15-16
うん?どちらか(あるいは両方)が偽者か?

>>15
>タスクスイッチはレコードロックと関係がある。

関係無いって。あると言うならその関係を説明してみそ。
001812NGNG
あのね
シングルタスク・シングルユーザのシステムだったら
ロックなんて基本的にいらないのよね
001914NGNG
あー、難しい言葉を使いたい年頃なのね。
わかった、わかった。もういい。
0020デフォルトの名無しさんNGNG
で、結局そのVBマガジンの特集はどうだったんでしょうか?
0021デフォルトの名無しさんNGNG
そんなこたー仕事に関係なきゃ知る必要ないじゃんか
仕事で使うのならマニュアル読め
といいたいところだが

MS SQL-Serverのことはよく知らないのだが
BeginTrans から CommitTrans の間のselect文は
レコードロックがデフォルトになってるシステムが多いから
ある意味では正しいが、間違いであることは>>1の例が示している。
それ以上のことは、自分で調べてくれ。

途中からVBの言葉を使いながらより一般的な話をしてるのは許してくださいね。
002220NGNG
あ、いや、
>>1
>VBMに書いてある事が間違っているのでしょうか

が正しい批評だったのかどうかを知りたいんですが。
翔泳社の雑誌は結構信頼してるから。
0023cafeNGNG
>>22
読んでないけど、間違ってはいないのだろう。
雑誌の整合性ってのは複数DBの同時更新なんか
を意味しているんだろうから。
>>21
>BeginTrans から CommitTrans の間のselect文は
>レコードロックがデフォルトになってるシステムが多いから
そうだったんだ。しらんかったな。
0024デフォルトの名無しさんNGNG
>>21
>BeginTrans から CommitTrans の間のselect文は
>レコードロックがデフォルトになってるシステムが多いから

多いか少ないかは解らないが、メジャーなRDBMSはこうはなっていない。
明示的にロックしなければいけない。

ex)Oracle, Informix, Sybase, PostgreSQL

MS SQL Serverは使ったこと無いが、おそらくロックはかからないと思う。(Sybaseの流れで)
DB2は知りません。

また、SQL92やSQL99でも、トランザクションの機能で、読み取った
行にデフォルトでロックがかかるようなモードは無いようです(認識ちがいかも)。
0025デフォルトの名無しさんNGNG
Private Sub Command1_Click()
Dim CN As ADODB.Connection
Dim RS As ADODB.Recordset
Dim Suu As Currency
Dim OpenStr As String

OpenStr = "Provider=SQLOLEDB;User Id=sa;Password=''"
Set CN = New ADODB.Connection

CN.Open OpenStr
CN.BeginTrans
Set RS = CN.Execute("SELECT Suu FROM Test.dbo.ZAIKO (UPDLOCK) WHERE ID=1")
Suu = RS("Suu") - 1
RS.Close
Set RS = Nothing
Stop 'ここで別 PC の Access でSuu変更
CN.Execute ("UPDATE Test.dbo.ZAIKO SET Suu=" & Suu & " WHERE ID=1")
CN.CommitTrans
CN.Close
Set CN = Nothing
End Sub

といった感じでテストしてみたが(UPDLOCK)があるとAccess側に"このレコードは他のユーザによって変更されています..."
といった表示が出てくる。
無いとAccessの更新が一度有効となりその後UPDATE文が有効となる。
(UPDLOCK)はOracleではfor updateだったと思う。
業務要件でどっちもありだと思うが、BeginTrans、CommitTransとトランザクションのアトミック
属性の話ならVBMの例はちょっと問題だと思うな。
0026デフォルトの名無しさんNGNG
>>25
>(略)
>無いとAccessの更新が一度有効となりその後UPDATE文が有効となる。

えーと、それって普通じゃ・・・。何番に対するコメントなんでしょう?
Accessも他のメジャーなRDBMSと同じですよ、という例なんでしょうか。

>トランザクションのアトミック
>属性の話ならVBMの例はちょっと問題だと思うな。

「アトミック属性」というのが何だか良く解りませんが、その「VBMの例」
は、どういうもので、どう問題なんでしょう?
そこが知りたいのに・・・。
002721NGNG
訂正します
>BeginTrans から CommitTrans の間のselect文は
>レコードロックがデフォルトになってるシステムが多いから
レコードロックがデフォルトになってるシステムもあるかもしれない
002825NGNG
>>26
>えーと、それって普通じゃ・・・
そうなんだけど、1で
>BeginTrans から CommitTrans の間のSQL文は別の処理が入ら
>ないので整合性が保たれるというような事が書いてあるが...
の例なのに途中でAccessごときで更新がかかっちゃまずいじゃない。
やっぱり"別の処理が入らない"様にすべきじゃない?。
で(UPDLOCK)を入れると、BeginTrans からCommitTrans間でLOCKされて
"別の処理が入らない"様になる。だったら例としてはそのほうが良くはない?

RS.Close
Set RS = Nothing
Stop 'ここで別 PC の Access でSuu変更
の順なんでSELECT文で作ったカーソルは一応お役ごめんになるわけで、
そうなるとVBMの例では単にUpdate文の前でAccessでいじって、その結果を
Update文で上書きするって言う話になって、確かに"それって普通じゃ・・・"
って発言は正しいことになる。でもそれならBeginTrans 、CommitTransの効果の
意味はここで見えないことになっちゃって、エラーの時RollbackTransできます
くらいの話になっちゃう。"間のSQL文"てなに?ってことになるじゃない。
トランザクションの粒度が小さくてBeginTrans からCommitTrans間で2分されている
って言っても良いかも。

Select文に(UPDLOCK)があるとRS.Close、Set RS = NothingがあってもLockの効果
はBeginTrans、CommitTrans間で生きていて"別の処理が入らない"様になるわけで
そのほうが例としては適切じゃない?
この場合他の更新は追い出せて、自分のUpdate文はLockされないよって言う事も示せるし...。
トランザクションの粒度はBeginTrans、CommitTrans間と一致するわけで、粒度が大きく
なって、2つのSQL文を含んでめでたくBeginTrans、CommitTransでくくった複数のSQL
文を1トランザクションとして扱います。って効果が見えるし。
002926NGNG
>>28
あ、大きな勘違いが僕かあなたのどちらかにあります。
僕は>>1のコード片は1が考えたコードで、VBMに例として載っている
ものでは無い、と認識してます。

議論したいのはトランザクションの中で、ロックのかからないSelectをやって、
その結果を元に更新処理をするのは是か非か、意味があるか無いか、
ではなく(それは結論が出てますよね)、
・VBMの例とはどういうものか?
・VBMの解説とはどういうものか?
・それは不適切なもの、あるいは間違ったものなのか?
です。

うーん、気になるから、明日にでも立ち読みに行ってくるかな。
003025NGNG
>>29
あ、なるほどね、それなら同意見ですね。
そういやVBMだれか持ってたな探そうっと。
003126NGNG
めちゃ気になるので、昼休みに確認に行きました(w

VBの例は、>>1のコードと似たようなもので、
Select num 〜
Check_num
Update hoge set col = num +〜
みたいな感じでした。

本文には、「トランザクションの解説はしないが〜」とありました。
ロールバックすると、更新したものが元に戻るというような
記述はありました。

>>25のコードで、MS SQL Serverも、単一Selectはレコードロック
されないということが解ったので、この記事はちょっといただけ
ませんね。例え初心者向けの記事としても。

というか、この記事の筆者って、トランザクション処理のことが
わかって無いのかも。(あ、筆者の名前を確認するの忘れた)

どちらにせよ、トランザクション処理の見本としてVBMのコード
を参考にしてはいけない、という結論ですね。
>>25のコードをお手本にするべき。

あー、スッキリした(w
003226NGNG
記事の著者がわかった。
大澤文孝という人。

結構本を出してるみたい(cbook24で9冊Hit)だけど、データベース
関連の本は出してないなー。
なんか、畑違いのような気がするが、なんでこの人があの特集を
担当するようになったんだろう?
0033デフォルトの名無しさんNGNG
技術評論社の「すぐわかるSQL」でもトランザクション
に同じような例がでていて、select文でロックがかかると
書かれてます
ただ注釈があって、
データベース製品、またはトランザクションのアイソレーション
レベルによって、SELECT命令ではロックされない場合があります。
と注意書きがある。
MS-SQL Serverの場合、アイソレーションレベルがREPEATABLE READ以上の
場合は、SELECT命令のロックが、トランザクション修了まで、
継続するようである。(ただし、アイソレーションレベルの
デフォルトはREAD COMMITTEDのようである)
このような混乱を防ぐために、トランザクション中の
SELECT命令には、ロックモードを明記しておいたほうがよいと思う。
■ このスレッドは過去ログ倉庫に格納されています