線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2726
推到 Plurk!
推到 Facebook!

請問多執行序要更新資料庫會出現目前已被鎖定,無法更新的問題

答題得分者是:malanlk
17kobe
初階會員


發表:86
回覆:73
積分:31
註冊:2007-07-30

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-03-01 00:06:09 IP:220.132.xxx.xxx 訂閱
主程式寫
//用for 迴圈來啟動執行序
for ....
TsingleProfit.Create;


執行序程式寫有
TADOConn1 := TADOConnection.Create(nil);
TADOQuery1 := TADOQuery.create(nil);
TADOConn1.Provider := 'Microsoft.ACE.OLEDB.12.0';
TADOConn1.LoginPrompt := false;
TADOConn1.Mode := cmShareDenyNone;
TADOConn1.ConnectionString := 'User ID=Admin;Persist Security Info=False;' 'Data Source=' g_sTempDBFile ';';
TADOConn1.KeepConnection := true;
TADOConn1.Connected := True;
TADOQuery1.Connection := TADOConn1;


TADOQuery1.SQL.Clear;
TADOQuery1.SQL.Add('update 自訂清單 set ' db_field[i] '=''' s_profit[i] ''' where 基金名稱=''' m_FundName ''' and 群組=' inttostr(m_group) ';');
TADOQuery1.ExecSQL;

執行到update時,會不定時出現"無法更新,目前已被鎖定"的例外情況。不知道是為什麼,請大大幫忙
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-03-01 02:50:37 IP:61.219.xxx.xxx 訂閱
建立一個 global TCriticalSection 變數 LockXY 將 ExecSQL 包住

===================引 用 17kobe 文 章===================
.....
TADOQuery1.SQL.Clear;
TADOQuery1.SQL.Add('update 自訂清單 set ' db_field[i] '=''' s_profit[i] ''' where 基金名稱=''' m_FundName ''' and 群組=' inttostr(m_group) ';');

LockXY.Acquire; { lock out other threads }
try
TADOQuery1.ExecSQL
finally
LockXY.Release;
end;;

執行到update時,會不定時出現"無法更新,目前已被鎖定"的例外情況。不知道是為什麼,請大大幫忙
pceyes
尊榮會員


發表:70
回覆:657
積分:1140
註冊:2003-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-03-01 10:21:07 IP:220.141.xxx.xxx 訂閱
左脚踩右脚,自己鎖自已,看看鎖定改用樂觀鎖定吧。
------
努力會更接近成功
17kobe
初階會員


發表:86
回覆:73
積分:31
註冊:2007-07-30

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-03-01 16:53:07 IP:220.132.xxx.xxx 訂閱
  謝謝你的回覆
我的更新已沒有問題
但是更新完我等所有thread都跑完後,去顯示結果
但是可能是ADOConnection共用,變成只顯示更新前的資料。
而要顯示新的資料變成要
ADOConnection.connected := false;
ADOConnection.connected := true;
下達這兩行指令才能抓到更新後的資料
而我不是確定這樣下法對不對,有什麼方法能ADOQuery到新資料,而不用下上面指令嗎
===================引 用 malanlk 文 章===================
建立一個 global TCriticalSection 變數 LockXY 將 ExecSQL 包住

===================引 用 17kobe 文 章===================
.....
TADOQuery1.SQL.Clear;
TADOQuery1.SQL.Add('update 自訂清單 set ' db_field[i] '=''' s_profit[i] ''' where 基金名稱=''' m_FundName ''' and 群組=' inttostr(m_group) ';');

LockXY.Acquire; { lock out other threads }
try
TADOQuery1.ExecSQL
finally
LockXY.Release;
end;;

執行到update時,會不定時出現"無法更新,目前已被鎖定"的例外情況。不知道是為什麼,請大大幫忙
編輯記錄
17kobe 重新編輯於 2008-03-01 16:57:50, 註解 無‧
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-03-01 17:01:45 IP:61.219.xxx.xxx 訂閱
重新再 Query 一次即可,不需要再 Disconnect/Connect
17kobe
初階會員


發表:86
回覆:73
積分:31
註冊:2007-07-30

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-03-01 18:38:21 IP:220.132.xxx.xxx 訂閱
query還是舊資料,但去資料庫看已更新完畢。
而且當主視窗關閉時,因為TCriticalSection是全域的,在主視窗的Create建立,在destroy,free掉,而這時執行序還在使用就會造成錯誤的問題,因為已被free。
編輯記錄
17kobe 重新編輯於 2008-03-02 01:40:03, 註解 無‧
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-03-02 03:07:30 IP:61.219.xxx.xxx 訂閱

===================引 用 17kobe 文 章===================
query還是舊資料,但去資料庫看已更新完畢。
而且當主視窗關閉時,因為TCriticalSection是全域的,在主視窗的Create建立,在destroy,free掉,而這時執行序還在使用就會造成錯誤的問題,因為已被free。

先將所有執行緒停掉再去 Free TCriticalSection

照你第一篇顯示的程式寫法, 你是在每一個執行緒內 create connection 並沒有共用, 檢查一下 IsolationLevel是否有設對
編輯記錄
malanlk 重新編輯於 2008-03-02 03:12:48, 註解 無‧
17kobe
初階會員


發表:86
回覆:73
積分:31
註冊:2007-07-30

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-03-02 20:31:10 IP:220.132.xxx.xxx 訂閱
^^   
IsolationLevel屬性改成ilReadUncommitted可以解決資料沒更新的問題。
還有在destroy的Free TCriticalSection之前,要先強制結束執行序(執行一半也不執行了),這個要用哪個指令呢,再跟你請教。
PS:目前只會等待所有執行序完畢後,才關掉主form,想要用強制關掉執行序,但好像有些安全問題,沒free掉之類的。
感謝你很有用的提示。
===================引 用 malanlk 文 章===================

===================引 用 17kobe 文 章===================
query還是舊資料,但去資料庫看已更新完畢。
而且當主視窗關閉時,因為TCriticalSection是全域的,在主視窗的Create建立,在destroy,free掉,而這時執行序還在使用就會造成錯誤的問題,因為已被free。

先將所有執行緒停掉再去 Free TCriticalSection

照你第一篇顯示的程式寫法, 你是在每一個執行緒內 create connection 並沒有共用, 檢查一下 IsolationLevel是否有設對
編輯記錄
17kobe 重新編輯於 2008-03-02 20:47:15, 註解 無‧
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-03-03 10:51:40 IP:218.211.xxx.xxx 訂閱
最好的辦法還是作個 Thread 的管理..
1. Thread 開始時就加入管理Thread 的 List
2. 等Thread結束後再發Message通知主程式 或是 在 Thread 的 OnTerminate 中告知主程式該 Thread 已經結束
3. 主程式收到 2. 的訊息就去拿掉 List 中對應的 Thread 紀錄

4. 程式結束時檢查 List 是否全部做完.. 沒做完就Show Message 並等一下再去Check

17kobe
初階會員


發表:86
回覆:73
積分:31
註冊:2007-07-30

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-03-06 23:40:43 IP:220.132.xxx.xxx 訂閱
安全關閉執行序沒問題
但資料庫又出現沒更新了。
更新完資料庫後,再去顯示資料庫的內容要注意什麼,都要第二次再去更新,再去顯示才會有上一次的資料。
是不是有緩存用的,還是什麼...
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#11 引用回覆 回覆 發表時間:2008-03-07 02:50:20 IP:61.219.xxx.xxx 訂閱
1. 您程式中Thread 的 ADOConnection 是共用 Data Module 裡的? 還是每個 Thread 自行建立? 
2. TADOConnection 的 Mode 也要注意一下...
17kobe
初階會員


發表:86
回覆:73
積分:31
註冊:2007-07-30

發送簡訊給我
#12 引用回覆 回覆 發表時間:2008-03-07 14:36:42 IP:60.250.xxx.xxx 訂閱
是自行建立的,當初是怕主視窗關閉會發生錯誤的問題。
而thread的 ADOConnection 裡的Mode是使用cmShareDenyNone;

我想可以再去把ADOConnection改都用主視窗的來試試。
===================引 用 malanlk 文 章===================
1. 您程式中Thread 的 ADOConnection 是共用 Data Module 裡的? 還是每個 Thread 自行建立?
2. TADOConnection 的 Mode 也要注意一下...
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#13 引用回覆 回覆 發表時間:2008-03-09 17:38:36 IP:61.219.xxx.xxx 訂閱
我的經驗是放在Data Module 共用 比放在主Form裡好。
系統時間:2024-05-09 5:34:45
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!