資料庫與多人訂位問題?為什麼還會訂到同一個位子 |
答題得分者是:aftcast
|
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
請教各位大大:
小弟試寫了一個訂位系統,為了避免多人使用,我設了一個訂位權利的鑰匙,誰先取得鑰匙,誰就可以先訂位 但多人同時執行的時候,偶爾還是會訂到同一個位子,小弟我這種方法感覺還是有漏洞,這種類似的問題有其他解決的方式嗎? 主程式訂位片段: [code cpp] //先看看有沒有人已經正在進行訂位(看別人是否已取得鑰匙) if Check_Lock('S') then begin showmessage('目前有人訂位中!!請稍候執行'); exit; end; try fm_MainMenu.ADOConnection1.BeginTrans; //先取得鑰匙(欄位update成1) if not Lock_Key('S',1) then begin exit; end; try //尋找空位(不能自由選擇,完全由系統從第一排空位開始找起到最後一排) //將該空位設成已訂位 //釋放鑰匙(欄位update成0) if not Lock_Key('S',0) then begin exit; end; fm_MainMenu.ADOConnection1.CommitTrans; ShowMessage('訂位成功'); except on E: Exception do begin fm_MainMenu.ADOConnection1.RollbackTrans; ShowMessage('訂位失敗, 異常訊息->' E.Message); Exit; end; end; finally if fm_MainMenu.ADOConnection1.InTransaction then fm_MainMenu.ADOConnection1.RollbackTrans; end; [/code] 副程式 [code cpp] function Check_Lock(S:string): boolean; //判斷該table是否已被鎖住 回傳false:沒鎖 true:鎖 begin result := false; try with fmPublic do begin //select [BIN_KEY] QPub1.SQL.Clear; if S='S' then QPub1.SQL.Text:='select BIN_KEY from BIN_KEY' QPub1.Open; if S='S' then begin if QPub1.FieldByName('BIN_KEY').AsInteger=0 then exit; end; end; except exit; end; result := true; end; function Lock_Key(S:string ; lock:integer): boolean; //lock BIN_KEY begin result := false; try with fmPublic do begin //update [BIN_KEY] QPub1.SQL.Clear; if S='S' then QPub1.SQL.Text:='update BIN_KEY set BIN_KEY=''' inttostr(lock) ''' ' QPub1.ExecSQL; end; except fm_MainMenu.ADOConnection1.RollbackTrans; showmessage('系統鎖住資料表 [BIN_KEY] 失敗!!'); exit; end; result := true; end; [/code] |
st33chen
尊榮會員 發表:15 回覆:591 積分:1201 註冊:2005-09-30 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
請問是什麼資料庫?
多人使用是指同一個軟體在不同的電腦同時使用嗎? 建議不要使用adoconnection裡的transaction,改用資料庫裡的transaction指令或是sql指令來lock table 或是row。 其實還是要先了解db是什麼才比較好解決。 若是用access這類的,那就要靠lock file的技巧來解決了。
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-11-17 20:59:28, 註解 無‧
|
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
aftcast大大:
我使用的資料庫是Oracle 10g....... 恩~~~多人使用指的是同一套軟體裝在不同電腦同時使用..... ===================引 用 aftcast 文 章=================== 請問是什麼資料庫? 多人使用是指同一個軟體在不同的電腦同時使用嗎? 建議不要使用adoconnection裡的transaction,改用資料庫裡的transaction指令或是sql指令來lock table 或是row。 其實還是要先了解db是什麼才比較好解決。 若是用access這類的,那就要靠lock file的技巧來解決了。
編輯記錄
lkkplayer 重新編輯於 2008-11-17 21:37:54, 註解 無‧
|
herbert2
尊榮會員 發表:58 回覆:640 積分:894 註冊:2004-04-16 發送簡訊給我 |
感覺上, 您的寫法有幾個問題:
(1) 永遠只有一個 Client (A) 可以訂位, 其他 Client (B....Z) 都須等待. A 若被旁騖耽擱, B....Z 會等得『起肖』! (高鐵購票系統翻版?) (2) 當您釋放鑰匙時, Client B....Z 之一便可能馬上取得鑰匙, 而與 A 訂到同一座位. 因 Server 同時與 Client A.....Z 連線, A 一釋放, 其它 Client 便稱隙溜進來了. (3) 應該比 (2) 先執行, 才可避免一座多賣. 但 (1) 仍是大問題. ===================引 用 lkkplayer 文 章=================== 請教各位大大: 小弟試寫了一個訂位系統,為了避免多人使用,我設了一個訂位權利的鑰匙,誰先取得鑰匙,誰就可以先訂位 但多人同時執行的時候,偶爾還是會訂到同一個位子,小弟我這種方法感覺還是有漏洞,這種類似的問題有其他解決的方式嗎? 主程式訂位片段: [code cpp] //先看看有沒有人已經正在進行訂位(看別人是否已取得鑰匙) if Check_Lock('S') then begin showmessage('目前有人訂位中!!請稍候執行'); // (1) ? end; try fm_MainMenu.ADOConnection1.BeginTrans; //先取得鑰匙(欄位update成1) if not Lock_Key('S',1) then begin exit; end; try //尋找空位(不能自由選擇,完全由系統從第一排空位開始找起到最後一排) //將該空位設成已訂位 //釋放鑰匙(欄位update成0) (2) ? if not Lock_Key('S',0) then begin exit; end; fm_MainMenu.ADOConnection1.CommitTrans; // (3) ? ShowMessage('訂位成功'); except on E: Exception do begin fm_MainMenu.ADOConnection1.RollbackTrans; ShowMessage('訂位失敗, 異常訊息->' E.Message); Exit; end; end; finally if fm_MainMenu.ADOConnection1.InTransaction then fm_MainMenu.ADOConnection1.RollbackTrans; end; [/code] 副程式 [code cpp] function Check_Lock(S:string): boolean; //判斷該table是否已被鎖住 回傳false:沒鎖 true:鎖 begin result := false; try with fmPublic do begin //select [BIN_KEY] QPub1.SQL.Clear; if S='S' then QPub1.SQL.Text:='select BIN_KEY from BIN_KEY' QPub1.Open; if S='S' then begin if QPub1.FieldByName('BIN_KEY').AsInteger=0 then exit; end; end; except exit; end; result := true; end; function Lock_Key(S:string ; lock:integer): boolean; //lock BIN_KEY begin result := false; try with fmPublic do begin //update [BIN_KEY] QPub1.SQL.Clear; if S='S' then QPub1.SQL.Text:='update BIN_KEY set BIN_KEY=''' inttostr(lock) ''' ' QPub1.ExecSQL; end; except fm_MainMenu.ADOConnection1.RollbackTrans; showmessage('系統鎖住資料表 [BIN_KEY] 失敗!!'); exit; end; result := true; end; [/code]
編輯記錄
herbert2 重新編輯於 2008-11-17 21:56:11, 註解 無‧
|
hotswin
中階會員 發表:72 回覆:92 積分:52 註冊:2003-11-06 發送簡訊給我 |
|
pceyes
尊榮會員 發表:70 回覆:657 積分:1140 註冊:2003-03-13 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
仔細的看了一下你的程式碼後,發現你的一些觀念不太正確。
我之前在電信公司上班,且兼資料庫管理師職務,處理的資料庫系統非常的大且複雜,所以給你幾個良心的經驗建議。 1/ 你對 transaction的機制不太熟。資料庫transaction本身就有自己lock的機制。所以你自己又用了一個Check_Lock('S')之類的功能等於是脫褲子放屁,而且還讓效能變得很差。因為你的那功能若是正常,則表示同時間內所有的交易都將停止,這樣太過嚴了! 而資料庫本身的transaction的機制則智慧不少,它通常可以讓數個交易一起進行,但又不會錯誤。這是高階資料庫的必備功能,比如說oracle或是mssql這類的,那麼貴就是貴在這裡。所以,你不必在自己設個table然後update…check...等等等的。 2/ Begintrans之前就不用搞Check_Lock之類的東西。緊接著就是select 哪裡有空的,update 某些資料,然後commit。 3/ rollback的用法時機你可能有錯,你似乎認為在begintrans的過程中若有某資料update失敗之類的,會造成expect? 我不是很確定,但正統來說不該是在expect之內rollback。而是要在update的下一行使用 conn.Errors.Count 的值來得知是否有誤,若是回傳大於0則表有錯,那麼就立刻下rollback。以此推下去,每個update的後面都要check一下。 for pseudo code example: conn.execute('update table set col = 1' , i ); //conn.execute 的用法看下面幾點的說明 if ( i = 0 or conn.Errors.Count > 0 ) than rollback ,ShowMessage('訂位錯誤…'),exit conn.execute('update table2 set col = 123' , i ); if ( i = 0 or conn.Errors.Count > 0 ) than rollback ,ShowMessage('訂位錯誤…'),exit 4/ 請儘量不要使用ADO「原始」元件以外的元件,哪些哪? TADOQuery之類的…原始的只有幾個常用的 TADoconnection, TADOCommand, TADoDataset,這三個,其他的都是被borland又包起來的元件為了是讓過去使用TQuery?之類的人習慣。這裡元件有時候會無法把原元件的功能全展現,堪至出錯。你寫的下面幾行就是其一
5/所有在begintrans下的update指令都會自然造成該row 或是table鎖住直到commit,這是一種保護。但是select的部份則不一定會鎖住資料,這必需要看系統的isolate level設為多少,或者你可以自行在ado裡的property設定,但建議不要去動它。不過當你真的都搞不定時,就試一下這行吧cnn1.IsolationLevel = adXactRepeatableRead 它是connection的屬性。 6/ 在begintrans 下面的程式碼裡,一定不能含有任何與user可以互動的程式,比如說問他確定嗎? 因為萬一使用者因故離開,那就卡在哪裡了! 不過也不用太過度的緊張,好的資料庫可以設定timeout的時間,不過,還是別這樣搞就是! 7/ 有些時候update的資料會是0筆,這不算是異常,可能是沒有符合條件之類的,故我都是用conn.Execute(query,i); 來update資料。其中query就像是'update BIN_KEY set BIN_KEY=1' ,而i值就很重要了!! i 值可以告訴你update有沒有成功,當i >0 時表成功的影響幾列資料,0當然就是沒有任何資料被update。 所有的select 或是 update 的指令,通通可以用TAdoconnction.execute( )來完成! 小結一下: 把你的Check_Lock ,Lock_Key 二個function都刪了。但是在begintrans裡關於select 空位,update某資料的後面要加入conn.Errors.Count 的判別,然後rollback。你是否會擔心多個交易搞在一起的混亂情形? 不用擔心!! 資料庫會自己搞定。當然,某些情形下可能要自己調整 isolate level,但這是進階的工作,暫不談。 如果改了還是有問題,那麼就該懷疑你的ado provider是否支持begintrans的功能,我是指provider不是你的ocrale,oracle當然本身是有的! 補充: 使用transaction來解決你的問題是肯定可行的!! 因為是最正統的作法! 但經常的時候也可以選別種模式,比如上篇pceyes說的戶政事務所的故事 ^_^ 也是不錯的做法。 希望你把我每一個條列的內容都深思一下,再去修改程式~ 以上所述都是指高階的db才有的,如orcale或mssql之類的。其他如access之類的單機db則不適用!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
aftcast大大:
1.假如找到位子(select)與訂位(update)之間又加了一些蠻長的程式碼,最後才訂位(update),會造成找到同一個位子嗎? 2.adXactRepeatableRead是什麼意思?好像還有其他選項說......看起來感覺我應該選Readcommit?使用者只能讀我commit後的東西。 3.看來要好好看有關資料庫的東西。完全不熟...... ===================引 用 aftcast 文 章=================== 仔細的看了一下你的程式碼後,發現你的一些觀念不太正確。 我之前在電信公司上班,且兼資料庫管理師職務,處理的資料庫系統非常的大且複雜,所以給你幾個良心的經驗建議。 1/ 你對 transaction的機制不太熟。資料庫transaction本身就有自己lock的機制。所以你自己又用了一個Check_Lock('S')之類的功能等於是脫褲子放屁,而且還讓效能變得很差。因為你的那功能若是正常,則表示同時間內所有的交易都將停止,這樣太過嚴了! 而資料庫本身的transaction的機制則智慧不少,它通常可以讓數個交易一起進行,但又不會錯誤。這是高階資料庫的必備功能,比如說oracle或是mssql這類的,那麼貴就是貴在這裡。所以,你不必在自己設個table然後update…check...等等等的。 2/ Begintrans之前就不用搞Check_Lock之類的東西。緊接著就是select 哪裡有空的,update 某些資料,然後commit。 3/ rollback的用法時機你可能有錯,你似乎認為在begintrans的過程中若有某資料update失敗之類的,會造成expect? 我不是很確定,但正統來說不該是在expect之內rollback。而是要在update的下一行使用 conn.Errors.Count 的值來得知是否有誤,若是回傳大於0則表有錯,那麼就立刻下rollback。以此推下去,每個update的後面都要check一下。 for pseudo code example: conn.execute('update table set col = 1' , i ); //conn.execute 的用法看下面幾點的說明 if ( i = 0 or conn.Errors.Count > 0 ) than rollback ,ShowMessage('訂位錯誤…'),exit conn.execute('update table2 set col = 123' , i ); if ( i = 0 or conn.Errors.Count > 0 ) than rollback ,ShowMessage('訂位錯誤…'),exit 4/ 請儘量不要使用ADO「原始」元件以外的元件,哪些哪? TADOQuery之類的…原始的只有幾個常用的 TADoconnection, TADOCommand, TADoDataset,這三個,其他的都是被borland又包起來的元件為了是讓過去使用TQuery?之類的人習慣。這裡元件有時候會無法把原元件的功能全展現,堪至出錯。你寫的下面幾行就是其一
5/所有在begintrans下的update指令都會自然造成該row 或是table鎖住直到commit,這是一種保護。但是select的部份則不一定會鎖住資料,這必需要看系統的isolate level設為多少,或者你可以自行在ado裡的property設定,但建議不要去動它。不過當你真的都搞不定時,就試一下這行吧cnn1.IsolationLevel = adXactRepeatableRead 它是connection的屬性。 6/ 在begintrans 下面的程式碼裡,一定不能含有任何與user可以互動的程式,比如說問他確定嗎? 因為萬一使用者因故離開,那就卡在哪裡了! 不過也不用太過度的緊張,好的資料庫可以設定timeout的時間,不過,還是別這樣搞就是! 7/ 有些時候update的資料會是0筆,這不算是異常,可能是沒有符合條件之類的,故我都是用conn.Execute(query,i); 來update資料。其中query就像是'update BIN_KEY set BIN_KEY=1' ,而i值就很重要了!! i 值可以告訴你update有沒有成功,當i >0 時表成功的影響幾列資料,0當然就是沒有任何資料被update。 所有的select 或是 update 的指令,通通可以用TAdoconnction.execute( )來完成! 小結一下: 把你的Check_Lock ,Lock_Key 二個function都刪了。但是在begintrans裡關於select 空位,update某資料的後面要加入conn.Errors.Count 的判別,然後rollback。你是否會擔心多個交易搞在一起的混亂情形? 不用擔心!! 資料庫會自己搞定。當然,某些情形下可能要自己調整 isolate level,但這是進階的工作,暫不談。 如果改了還是有問題,那麼就該懷疑你的ado provider是否支持begintrans的功能,我是指provider不是你的ocrale,oracle當然本身是有的! 補充: 使用transaction來解決你的問題是肯定可行的!! 因為是最正統的作法! 但經常的時候也可以選別種模式,比如上篇pceyes說的戶政事務所的故事 ^_^ 也是不錯的做法。 希望你把我每一個條列的內容都深思一下,再去修改程式~ 以上所述都是指高階的db才有的,如orcale或mssql之類的。其他如access之類的單機db則不適用! |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
1/ 把那一堆找位子到訂位的一整段包在transaction的碼貼出來。
2/ adXactRepeatableRead 比Readcommit 層級更嚴(從字面上你會以為Readcommit比較嚴對吧?),很難簡短的說清楚,所以用我說的就是了ok? ===================引 用 lkkplayer 文 章=================== aftcast大大: 1.假如找到位子(select)與訂位(update)之間又加了一些蠻長的程式碼,最後才訂位(update),會造成找到同一個位子嗎? 2.adXactRepeatableRead是什麼意思?好像還有其他選項說......看起來感覺我應該選Readcommit?使用者只能讀我commit後的東西。 3.看來要好好看有關資料庫的東西。完全不熟......
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
aftcast大大:
附上我的程式碼......請您指點一下。 [code cpp] //找空位 SEAT_NO:=GET_SEAT(StrToInt(ROW_NO),RadioGroup1.ItemIndex); if SEAT_NO='Error' then begin fm_MainMenu.ADOConnection1.RollbackTrans; ShowMessage('目前無空位'); exit; end; ADOQuery1.First; i:=0; NAME:='00000000'; while not ADOQuery1.Eof do begin if trim(ADOQuery1.FieldByName('NAME').AsString) <> NAME then begin i:=i 1; QTmp2.Close; QTmp2.SQL.Text:='SELECT NAME,SUM(QTY) AS QTY FROM MENU_INFO_TMP WHERE NAME=''' trim(ADOQuery1.FieldByName('NAME').AsString) ''' GROUP BY NAME '; QTmp2.Open; QTmp1.Close; QTmp1.SQL.Text:='SELECT MAX(CHK_DATE) AS CHK_DATE, MIN(STOREIN_DATE) AS STOREIN_DATE FROM MENU_INFO_TMP WHERE NAME=''' trim(ADOQuery1.FieldByName('NAME').AsString) ''' '; QTmp1.Open; QTmp.Close; QTmp.SQL.Text:='Insert Into SET_DET(SEQ_NO,RECV_TIME,DET_NO,NAME,QTY,STOREIN_DATE,CHK_DATE) ' 'Values' '(''' seq ''',' 'TO_DATE(''' sysdate ''',''YYYYMMDDHH24MISS''),' '''' IntToStr(i) ''',' '''' trim(ADOQuery1.FieldByName('NAME').AsString) ''',' ''''',' '''' trim(ADOQuery1.FieldByName('UNITS').AsString) ''',' '''' trim(QTmp2.FieldByName('QTY').AsString) ''',' 'TO_DATE(''' FormatDateTime('YYYYMMDD',QTmp1.FieldByName('STOREIN_DATE').AsDateTime) ''',''YYYYMMDD''),' 'TO_DATE(''' FormatDateTime('YYYYMMDD',QTmp1.FieldByName('CHK_DATE').AsDateTime) ''',''YYYYMMDD''))'; QTmp.ExecSQL; end; ADOQuery1.Next; end; QTmp.Close; QTmp.SQL.Text:='Insert Into SET_MAS(SEQ_NO,RECV_TIME,SEAT_NO,DET_COUNT,ROW_NO,USER_ID) ' 'Values' '(''' seq ''',TO_DATE(''' sysdate ''',''YYYYMMDDHH24MISS''),' '''' SEAT_NO ''',''' inttostr(i) ''',''' ROW_NO ''',''' fm_MainMenu.UserName ''')'; QTmp.ExecSQL; //訂位 QTmp.Close; QTmp.SQL.Text := 'Update SEAT_BAS Set SEAT_STATE=''M'' Where SEAT_NO=''' SEAT_NO ''' '; QTmp.ExecSQL; [/code] ===================引 用 aftcast 文 章=================== 1/ 把那一堆找位子到訂位的一整段包在transaction的碼貼出來。 2/ adXactRepeatableRead 比Readcommit 層級更嚴(從字面上你會以為Readcommit比較嚴對吧?),很難簡短的說清楚,所以用我說的就是了ok? ===================引 用 lkkplayer 文 章=================== aftcast大大: 1.假如找到位子(select)與訂位(update)之間又加了一些蠻長的程式碼,最後才訂位(update),會造成找到同一個位子嗎? 2.adXactRepeatableRead是什麼意思?好像還有其他選項說......看起來感覺我應該選Readcommit?使用者只能讀我commit後的東西。 3.看來要好好看有關資料庫的東西。完全不熟...... |
christie
資深會員 發表:30 回覆:299 積分:475 註冊:2005-03-25 發送簡訊給我 |
Hi,請試試看!
//找空位 SEAT_NO:=GET_SEAT(StrToInt(ROW_NO), RadioGroup1.ItemIndex); if SEAT_NO='Error' then begin fm_MainMenu.ADOConnection1.RollbackTrans; ShowMessage('目前無空位'); exit; end; // 設一個temp Table: SEAT_BANK 含位置表 Qtmp.SQL.Text:=Format('Delete from SEAT_BANK where SEAT_NO=''%S''',[seat_no]); Qtmp.ExecSQL; IF Qtmp.RowsAffected > 0 then BEGIN ADOQuery1.First; i:=0; NAME:='00000000'; while not ADOQuery1.Eof do begin if trim(ADOQuery1.FieldByName('NAME').AsString) <> NAME then begin i:=i 1; QTmp2.Close; QTmp2.SQL.Text:='SELECT NAME,SUM(QTY) AS QTY FROM MENU_INFO_TMP WHERE NAME=''' trim(ADOQuery1.FieldByName('NAME').AsString) ''' GROUP BY NAME '; QTmp2.Open; QTmp1.Close; QTmp1.SQL.Text:='SELECT MAX(CHK_DATE) AS CHK_DATE, MIN(STOREIN_DATE) AS STOREIN_DATE FROM MENU_INFO_TMP WHERE NAME=''' trim(ADOQuery1.FieldByName('NAME').AsString) ''' '; QTmp1.Open; QTmp.Close; QTmp.SQL.Text:='Insert Into SET_DET(SEQ_NO,RECV_TIME,DET_NO,NAME,QTY,STOREIN_DATE,CHK_DATE) ' 'Values' '(''' seq ''',' 'TO_DATE(''' sysdate ''',''YYYYMMDDHH24MISS''),' '''' IntToStr(i) ''',' '''' trim(ADOQuery1.FieldByName('NAME').AsString) ''',' ''''',' '''' trim(ADOQuery1.FieldByName('UNITS').AsString) ''',' '''' trim(QTmp2.FieldByName('QTY').AsString) ''',' 'TO_DATE(''' FormatDateTime('YYYYMMDD',QTmp1.FieldByName('STOREIN_DATE').AsDateTime) ''',''YYYYMMDD''),' 'TO_DATE(''' FormatDateTime('YYYYMMDD',QTmp1.FieldByName('CHK_DATE').AsDateTime) ''',''YYYYMMDD''))'; QTmp.ExecSQL end; ADOQuery1.Next; end; QTmp.SQL.Text:='Insert Into SET_MAS(SEQ_NO,RECV_TIME,SEAT_NO,DET_COUNT,ROW_NO,USER_ID) ' 'Values' '(''' seq ''',TO_DATE(''' sysdate ''',''YYYYMMDDHH24MISS''),' '''' SEAT_NO ''',''' inttostr(i) ''',''' ROW_NO ''',''' fm_MainMenu.UserName ''')'; QTmp.ExecSQL //訂位 QTmp.SQL.Text := 'Update SEAT_BAS Set SEAT_STATE=''M'' Where SEAT_NO=''' SEAT_NO ''' '; QTmp.ExecSQL; END ELSE BEGIN ShowMessage('Allocate SEAT_BANK failed, 請再試一次') END; // IF Qtmp.RowsAffected > 0 ===================引 用 pceyes 文 章=================== 在戶政事務所,會有一張紙,顯示新的身分證字號,各櫃台要登記新生兒時,會抄錄並註明姓名,然後劃線槓掉,有時阿公和兒子、媳婦喬不定,登記一半,還會先吵一架,然後回去開會,戶籍員要用立可百將表再塗掉。 比照這方法,另設一個temp Table,含位置表,當要劃位時,先刪掉temp table那位置,先刪先贏,其他人就看不到了,萬一客人放棄訂位,還可以再寫回去,給下一個櫃台訂位。
------
What do we live for if not to make life less difficult for each other? |
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
|
christie
資深會員 發表:30 回覆:299 積分:475 註冊:2005-03-25 發送簡訊給我 |
可否提供aftcast
的版本 ? Many Thanks. ===================引 用 lkkplayer 文 章=================== christie大大: 用您的建議測試結果是ok的,我另外也測試aftcast大大的建議結果也ok, 不過我個人認為這個必須以長時間來觀察才准.....目前想採用兩位的混合版...... 我就不信還會再發生........在此跟您與aftcast致上我的謝意...^^"
------
What do we live for if not to make life less difficult for each other? |
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
christie大大:
我只是把connection的屬性手動設成RepeatableRead,並且把我之前Check_Lock的東西都拿掉,其餘的就是您看到的東西了說。 不曉得這個對您有幫助嗎?我沒試的就是每個SQL下命(update),檢測是否有error然後rollback....... ===================引 用 christie 文 章=================== 可否提供aftcast 的版本 ? Many Thanks. ===================引 用 lkkplayer 文 章=================== christie大大: 用您的建議測試結果是ok的,我另外也測試aftcast大大的建議結果也ok, 不過我個人認為這個必須以長時間來觀察才准.....目前想採用兩位的混合版...... 我就不信還會再發生........在此跟您與aftcast致上我的謝意...^^" |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |