トップページ⇒tech
62コメント28KB

ASP+SQL Serverで切実に困ってます。

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
自分で本やWebを調べたんですけどわかんなくて・・・
たぶんすっごい基本的なことだと思うんで知ってる人いたらタスケテ。

ASP+MS SQL Serverで作ったWebのサービスに異常発生。
調べてみたらユニークでなきゃいけないIDがかぶってました。
どうやら
1.一番大きいIDを引っ張ってくる。
↓
2.それに+1する
↓
3.+1したIDをつけてINSERT。

っていうところで1→3が終わる前に他のユーザが1の処理を
はじめるとIDがかぶるってことがわかりました。
(ためしに自分で2台同時にボタンおしたらかぶりました)

会社でほかにわかる人がいないので凄い基本っぽい気がする
この問題が解決できません(涙
ロックとかトランザクションって調べたんですけどいまいち意味がわかってない
せいかうまくいきません。
17日の正午までメンテナンス中っていうページに差し替えて
しのいであるんだけどこのままじゃ・・・。
0002デフォルトの名無しさんNGNG
ADOを使っているとして、

処理1の前に
conn.BeginTrans
して、
処理1-3が成功したら
conn.CommitTrans
どこかで失敗したら
conn.RollbackTrans
する。(connはConnectionオブジェクト)

でもちゃんと勉強した方がいいよ。トランザクションも知らずにDB
アプリを組むのは無謀ですよ。
0003デフォルトの名無しさんNGNG
こたえてくれてありがとうございます。

上のような感じにやってるんですが、その「失敗したか」
っていうのをCommitTransする前にどうやって判断したらいいかがわからなくて・・・。
00041NGNG
CON.BeginTrans()

SQL = "SELECT TOP 1 bk_id FROM book ORDER BY bk_id DESC"
SET RS = CON.Execute(SQL)

If RS.EOF Then
newbk_id = 1
Else
newbk_id = RS("bk_id")+1
End If

SET rsInsert = Server.CreateObject("ADODB.Recordset")
rsInsert.Open "book", CON, 3, 3

rsInsert.AddNew
rsInsert("bk_id") = newbk_id
rsInsert.Update
rsInsert.Close

SQL = "SELECT TOP 1 bk_id FROM book ORDER BY bk_id DESC"
SET RS2 = CON.Execute(SQL)

if RS2("bk_id")+1 = newbk_id then
CON.CommitTrans
else
CON.RollBackTrans
response.redirect "error.asp"
end if

こんな感じなんですがものすごくだめな気がします>オレ
だれかお助けを・・・もちろん土日も会社です(今も)
うっ
0005デフォルトの名無しさんNGNG
SQLServer初心者だけど検索してみた。
http://www.acc.gr.jp/wwwdata/pinsql/19981228/836.html

本当は、設計が悪いといいたけどそういわれてもこまるでしょう。
bookをテーブルロックしたら副作用が出るかもしれないけど
その辺は全体をみないとわからないからとりあえず。
0006デフォルトの名無しさんNGNG
レコード作成してる糞処理をストアドにして
Application.Lock
ストアド実行
Application.Unlock
でダメ?俺もASP知らないけど、カウンタのサンプルでApplication.Lockって使ってたよ
0007<>NGNG
> 会社でほかにわかる人がいないので凄い基本っぽい気がする
> この問題が解決できません(涙
どんな会社だよ。本当か?
教えてもいいけどさ、つか他の人がロジックまで丁寧に書いてくれてる
からそれ以上言わないけどさ、
根本的に、誰も排他制御も知らん会社で仕事してる事が一番の問題
な気がするぞ。転職すれ。

君のコードで言うと
> SET RS2 = CON.Execute(SQL)
これをやったときに、RS2のプロパティかメソッドで何らかエラーが
拾えるはずだが(調べるのメンドイからそこは割愛するが、ワリィ)
その結果をによってCommitTransもしくはRollback
って感じじゃないのかね?
0008デフォルトの名無しさんNGNG
SQLServerならadLockOptimistic(3)でなくadLockPessimistic(2)でやってみれば?
他がオープン中のときは、処理が終わるまで待たされるようになる。
sSQL = "SELECT TOP 1 bk_id FROM book ORDER BY bk_id DESC"
Call rs.Open("book", CON, 3, 2)
If rs.EOF = True Then
  lNewId = 1
Else
  lNewId = rs("bk_id") + 1
End If
rs.AddNew
rs("bk_id") = lNewId
rs.Update
rs.Close

SQLServerなど信用できんというならば、ファイルロックを使うかな。
排他でオープンしようとするとエラーになるのでOnErrorResumeNextでErr.Number
をチェックして、オープンできるまでぐるぐる繰り返す。

OSのファイル処理など信用できんというならば、、、知らん。
0009 NGNG
1.一番大きいIDを引っ張ってくる。
SELECT MAX(bk_id) FROM book WITH(ROWLOCK)
0010 NGNG
DBの人はセマフォ知らないのか?
00111NGNG
Applicationってやつで他の奴が処理中だったら待つように作ってみたんだけど
「10人同時に押したら10人分まつのか!」っていわれてやり直しに・・・。
結局IDがかぶっててもいいように作り変えることになりました。
なんか負けた感が強いです。
■ このスレッドは過去ログ倉庫に格納されています