全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:7561
推到 Plurk!
推到 Facebook!

多線程(MultiThread)+BDE+Oracle database 頻繁出錯(ORA-12560,ORA-03113)

答題得分者是:carstyc
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-06-30 17:59:51 IP:221.224.xxx.xxx 訂閱
環境描述 
OS:WINDOWS XP
DEVELOP TOOL:DELPHI 6.0
BDE Ver:5.01
Oracle client:ver 8.1.7
Oracle DB:9i
newwok:PL LAN--switch-firwall-Company LAN--db server(Run on sun SOLARIS)
程式描述:
物料驗證與追蹤系統(SMT PVS&PTS)
主程序用來上料,確認,檢驗
線程1:PTS,物料追溯,link sn,reel,扣reel料數量
線程2:PVS,驗證是否缺料,多料,錯料
線程3:採用FTP讀取SPI,AOI的測試資料,收集SN資訊;
每個線程都按delphi推薦的模式;擁有獨立的database,session
問題描述:
程式運行一段時間後有報如下錯誤:
-------------------------------------------------------------------------------
以”ORA-12560: TNS:協定介面程式錯誤”為主;其他還有
”ORA-12571: TNS:封包寫入器失敗”;
”ORA-03114: 未與 ORACLE 相連”
-------------------------------------------------------------------------------
平均1個多小時出一次錯誤;最長4個小時
出錯後程式有自動關閉資料庫database.close,但錯誤依舊迴圈;
關閉application後再開啟OK,運行一段時間錯誤重現
期間TNSPING DB正常
有請DBA查看dbServer log沒有發現類似錯誤
有請網路管理員查看switch,firewall;沒發現對應的錯誤,流量也在可接受範圍內(1M/PER PC)
××××××××××××××××××××××××××××××××××××××××××××××××××××

為了找尋問題的根源,有寫一支小程式(類比PTS,3個線程一個主程序;資料量要比PTS少很多),不斷的隨機往database裏面insert,select,delete資料
抽取了24小時內的log
結果有出現5次中斷,最長間隔12小時,最短0.5小時:每次的錯誤順序為:(與PTS的錯誤有些差異)
-------------------------------------------------------------------------------
Lost communication with SQL server.ORA-03113: 通訊通道上出現 EOF
General SQL error. ORA-03114: 未與 ORACLE 相連
------------------------------------------------------------------------------
但同時段卻沒有對應的ping丟包現象且此程序出錯的時間和PTS程序的錯誤時間也不匹配,可以排出網路的問題!
難道BDE多線程在資料量大且頻繁作業(每秒可能有上百筆資料要處理)的時候及其不穩定?google了下也沒發現類似的問題!

盼望高手能給與指點!!萬分感謝!
編輯記錄
dust.zhu 重新編輯於 2009-07-03 09:02:06, 註解 無‧
frappe
中階會員


發表:88
回覆:114
積分:95
註冊:2008-10-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-07-01 22:51:35 IP:118.231.xxx.xxx 訂閱
同一個Query如果需要24小時不斷執行,
需要釋放記憶體,不然程式容易當掉

這個是之前去資策會上課,老師教的,
試試看吧,希望對你有用^^

迴圈.....
Query1.Prepared:=false;
Query1.Prepared:=true;
Query1.Close;
........
Query1.Open;

編輯記錄
frappe 重新編輯於 2009-07-01 22:52:15, 註解 無‧
frappe 重新編輯於 2009-07-01 22:52:58, 註解 無‧
frappe 重新編輯於 2009-07-01 22:53:29, 註解 無‧
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-07-03 08:50:16 IP:221.224.xxx.xxx 訂閱
十分感謝frappe的答復!前兩天有休假沒及時回復!

程序中的tquery確實沒用到close,基本都是

query.SQL.Clear;
query.SQL.Add(''..);
query.ParamByName('..').AsString :=..;
......................................
query.Open/.ExecSQL;

但delphi幫助文檔有這樣的語句:

“When you change the text of a query at runtime, the query is automatically closed and unprepared.”

所以鄙人認為可以不寫close,prepare代碼,
在調用query.sql.clear時系統會自動做這個動作;不知理解是否有誤?

這個問題現在依舊沒有解決,出了這種錯誤,產線只能關了程序再開,很讓人頭疼!
希望有前輩高人能指點,小弟不勝感激!

編輯記錄
dust.zhu 重新編輯於 2009-07-03 08:57:04, 註解 無‧
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-07-05 00:34:15 IP:118.167.xxx.xxx 未訂閱
建議你可以更新
bde及oracle client的版本,或許可以直接解決你的問題

另外,針對你所說的錯誤訊息,我在其它的網站上有看到類似的解決做法
http://www.itpub.net/viewthread.php?tid=124145
你可以參考看看


===================引 用 dust.zhu 文 章===================
環境描述
OS:WINDOWS XP
DEVELOP TOOL:DELPHI 6.0
BDE Ver:5.01
Oracle client:ver 8.1.7
Oracle DB:9i
newwok:PL LAN--switch-firwall-Company LAN--db server(Run on sun SOLARIS)
程式描述:
物料驗證與追蹤系統(SMT PVS&PTS)
主程序用來上料,確認,檢驗
線程1:PTS,物料追溯,link sn,reel,扣reel料數量
線程2:PVS,驗證是否缺料,多料,錯料
線程3:採用FTP讀取SPI,AOI的測試資料,收集SN資訊;
每個線程都按delphi推薦的模式;擁有獨立的database,session
問題描述:
程式運行一段時間後有報如下錯誤:
-------------------------------------------------------------------------------
以”ORA-12560: TNS:協定介面程式錯誤”為主;其他還有
”ORA-12571: TNS:封包寫入器失敗”;
”ORA-03114: 未與 ORACLE 相連”
-------------------------------------------------------------------------------
平均1個多小時出一次錯誤;最長4個小時
出錯後程式有自動關閉資料庫database.close,但錯誤依舊迴圈;
關閉application後再開啟OK,運行一段時間錯誤重現
期間TNSPING DB正常
有請DBA查看dbServer log沒有發現類似錯誤
有請網路管理員查看switch,firewall;沒發現對應的錯誤,流量也在可接受範圍內(1M/PER PC)


為了找尋問題的根源,有寫一支小程式(類比PTS,3個線程一個主程序;資料量要比PTS少很多),不斷的隨機往database裏面insert,select,delete資料
抽取了24小時內的log
結果有出現5次中斷,最長間隔12小時,最短0.5小時:每次的錯誤順序為:(與PTS的錯誤有些差異)
-------------------------------------------------------------------------------
Lost communication with SQL server.ORA-03113: 通訊通道上出現 EOF
General SQL error. ORA-03114: 未與 ORACLE 相連
------------------------------------------------------------------------------
但同時段卻沒有對應的ping丟包現象且此程序出錯的時間和PTS程序的錯誤時間也不匹配,可以排出網路的問題!
難道BDE多線程在資料量大且頻繁作業(每秒可能有上百筆資料要處理)的時候及其不穩定?google了下也沒發現類似的問題!

盼望高手能給與指點!!萬分感謝!
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-07-06 13:41:11 IP:221.224.xxx.xxx 訂閱
感謝GrandRURU的答復!
問題發生期間有請DBA查看database log沒有發現任何問題
現在只能更新下BDE的版本試試了!不到萬不得已,真的不想改代碼(ado/dbexpress),工作量太大!
frappe
中階會員


發表:88
回覆:114
積分:95
註冊:2008-10-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-07-06 16:20:48 IP:61.20.xxx.xxx 訂閱
你可以不寫Close,
但是Prepare一定要寫,
因為這是用在資料庫最佳化與清除記憶體


===================引 用 dust.zhu 文 章===================
十分感謝frappe的答復!前兩天有休假沒及時回復!

程序中的tquery確實沒用到close,基本都是

query.SQL.Clear;
query.SQL.Add(''..);
query.ParamByName('..').AsString :=..;
......................................
query.Open/.ExecSQL;

但delphi幫助文檔有這樣的語句:

“When you change the text of a query at runtime, the query is automatically closed and unprepared.”

所以鄙人認為可以不寫close,prepare代碼,
在調用query.sql.clear時系統會自動做這個動作;不知理解是否有誤?

這個問題現在依舊沒有解決,出了這種錯誤,產線只能關了程序再開,很讓人頭疼!
希望有前輩高人能指點,小弟不勝感激!

GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-07-07 08:16:14 IP:203.75.xxx.xxx 未訂閱
認同+1
===================引 用 frappe 文 章===================
你可以不寫Close,
但是Prepare一定要寫,
因為這是用在資料庫最佳化與清除記憶體
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-07-07 09:01:16 IP:221.224.xxx.xxx 訂閱
更新BDE5.2,BDE MEMORYSIZE加大一倍;
從12小時內的log看無任何效果!
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-07-07 09:55:08 IP:203.75.xxx.xxx 未訂閱
Oracle 內有調整嗎?
Oracle Client 有更新嗎?
===================引 用 dust.zhu 文 章===================
更新BDE5.2,BDE MEMORYSIZE加大一倍;
從12小時內的log看無任何效果!
carstyc
資深會員


發表:16
回覆:254
積分:329
註冊:2003-07-18

發送簡訊給我
#10 引用回覆 回覆 發表時間:2009-07-07 22:16:50 IP:219.84.xxx.xxx 訂閱
請教一下,你說你的 Thread 都有獨立的 Database 跟 Session 。

但你的 Thread 是持續跑很長的一段時間? 還是每跑完一個動作,Thread 就 Free 掉了。等要做下一個動作時再起另一個新的Thread。

如果是跑完一個動作就 Free 掉,就沒有 Close 不 Close 或是 要不要 Prepare 的問題,因為你連 Thread 都釋放掉了,當然下一個Thread再起來的時候,就會有新的 DataBase 來建立新的 Connection了。

如果不是,而是一個Thread 持續跑很久,這時就有可能會有你說的這些問題。

我不確定你的Thread寫法是如何,但DB 會有某些設定,會影響到你的AP。

舉個例來說,DB會把某些Connection 太久沒有做動作,而把它視為異常,進而主動把它『幹掉』。讓資源回收,可再給別的AP使用。

比如(我猜測的), 你的Thread 見到現在沒事做,就休息個幾十分鐘,或更久,等到下一次要再去檢查有沒有事要做的時候,Connection 卻被 DB主動砍掉了,所以你的AP就有可能出現 這些錯誤訊息。

甚至我碰過另一個情況,我用一個大迴圈把要做的項目列出來,然後根據大迴圈的資料去跑小迴圈做運算,結果小迴圈因為筆數較多,運算較久,而此時大迴圈的 Connection 都沒動作,且超過一定時間,而 AP 就有 Excepion 跑出來了,因為DB認為這個Connection 太久沒動作,就把把它回收去了。此時,即時去DB看Error也不會有看到異常的log,因為這個動作屬於『正常回收作業』。


以上方向提供你參考,我覺得你的問題點應該也是類似,只是我不知道你Thread的運作方法為何? 無法幫你Debug。你自己再找找看。


對了,順帶提一下解決方式,如果你有 DBA的權限,就找到那個 Time out 時間的參數,把它調高。

如果沒有DBA權限,只能靠自己改AP的話,就只好定時去把Connection 做些動作,比如定時就去Select 某個最小的Table。只要讓Connection 有動作,DB就不會把它『幹掉』了...




===================引 用 dust.zhu 文 章===================
環境描述
OS:WINDOWS XP
DEVELOP TOOL:DELPHI 6.0
BDE Ver:5.01
Oracle client:ver 8.1.7
Oracle DB:9i
newwok:PL LAN--switch-firwall-Company LAN--db server(Run on sun SOLARIS)
程式描述:
物料驗證與追蹤系統(SMT PVS&PTS)
主程序用來上料,確認,檢驗
線程1:PTS,物料追溯,link sn,reel,扣reel料數量
線程2:PVS,驗證是否缺料,多料,錯料
線程3:採用FTP讀取SPI,AOI的測試資料,收集SN資訊;
每個線程都按delphi推薦的模式;擁有獨立的database,session
問題描述:
程式運行一段時間後有報如下錯誤:
-------------------------------------------------------------------------------
以”ORA-12560: TNS:協定介面程式錯誤”為主;其他還有
”ORA-12571: TNS:封包寫入器失敗”;
”ORA-03114: 未與 ORACLE 相連”
-------------------------------------------------------------------------------
平均1個多小時出一次錯誤;最長4個小時
出錯後程式有自動關閉資料庫database.close,但錯誤依舊迴圈;
關閉application後再開啟OK,運行一段時間錯誤重現
期間TNSPING DB正常
有請DBA查看dbServer log沒有發現類似錯誤
有請網路管理員查看switch,firewall;沒發現對應的錯誤,流量也在可接受範圍內(1M/PER PC)
חחחחחחחחחחחחחחחחחחחחחחחחחח

為了找尋問題的根源,有寫一支小程式(類比PTS,3個線程一個主程序;資料量要比PTS少很多),不斷的隨機往database裏面insert,select,delete資料
抽取了24小時內的log
結果有出現5次中斷,最長間隔12小時,最短0.5小時:每次的錯誤順序為:(與PTS的錯誤有些差異)
-------------------------------------------------------------------------------
Lost communication with SQL server.ORA-03113: 通訊通道上出現 EOF
General SQL error. ORA-03114: 未與 ORACLE 相連
------------------------------------------------------------------------------
但同時段卻沒有對應的ping丟包現象且此程序出錯的時間和PTS程序的錯誤時間也不匹配,可以排出網路的問題!
難道BDE多線程在資料量大且頻繁作業(每秒可能有上百筆資料要處理)的時候及其不穩定?google了下也沒發現類似的問題!

盼望高手能給與指點!!萬分感謝!
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#11 引用回覆 回覆 發表時間:2009-07-08 09:41:52 IP:221.224.xxx.xxx 訂閱
感謝carstyc的回復
datamodule中有對應線程的database,session且每個線程只有一對;database.sessionname:=Session.sessionname,
thread執行在一個迴圈中,會持續跑很長的時間,因此不存在“太久沒有做動作”這個問題
線程的邏輯大概如下,這個線程的tquery是自動創建,其它兩個線程引用了datamodule中的tquery


[code delphi]
procedure TPTSThread.Execute;
const
C_SECOND = 1 / 8640;//10s
begin
{ Place thread code here
}
try
try
{建立線程和ADO組件的關系(線程中有用到一個自動創建的ado組件,
僅用于讀取本地access database中的數據)}
CoInitialize(nil);
//初始化系統參數
IniParameters;
while True do
begin
try
if FNextProcessTime < Now then
begin
//如果線程中止,跳出循環
if Terminated then
Break;
//當前此指針函數為空;DoBeforeProcessed:=nil;
if Assigned(DoBeforeProcessed) then
Synchronize(DoBeforeProcessed);
//check Process執行的條件是否滿足
if CheckInputs then
begin
//如果線程中止,跳出循環
if Terminated then
Break;
{主處理邏輯;link sn,reel;扣減reel當前數量;如果reel數量耗完則下架,
如果此reel有接料(備用reel),上架接料reel(參與link sn,reel,扣減數量)
此邏輯用的tdatabase來源于datamodule,在線程create時作參數傳入;
其它所有的tquery全部在線程create內部自動創建}
Process;
end;
FNextProcessTime := NOW C_SECOND;
//當前此指針函數為空;DoAfterProcessed:=nil;
if Assigned(DoAfterProcessed) then
Synchronize(DoAfterProcessed);
//如果線程中止,跳出循環
if Terminated then
Break;
end
else
Sleep(C_MILLISECOND);//等待200毫秒;釋放cpu
//如果線程中止,跳出循環
if Terminated then
Break;
except
on e: Exception do
begin
FUserMessages := e.Message;
//如果有出現“ora-...”等database連接的錯誤,close database
if IsDBException(FUserMessages) then
FDBOracle.Close;//此處FDBOracle引用了datamodule中的database
//顯示給用戶系統異常信息,不需要用戶確認
FDialogType := dtNoDialog;
Synchronize(MessagesToUser);
end;
end;
end;
except
on e: Exception do
begin
//顯示給用戶系統異常信息,需要用戶確認
FUserMessages := e.Message;
FDialogType := dtConfirmDialog;
Synchronize(MessagesToUser);
end;
end;
finally
//釋放資源
FreeResource;
CoUninitialize;
end;
end;
[/code]
編輯記錄
dust.zhu 重新編輯於 2009-07-08 09:44:10, 註解 無‧
dust.zhu 重新編輯於 2009-07-08 10:08:29, 註解 無‧
dust.zhu 重新編輯於 2009-07-08 10:11:19, 註解 無‧
carstyc
資深會員


發表:16
回覆:254
積分:329
註冊:2003-07-18

發送簡訊給我
#12 引用回覆 回覆 發表時間:2009-07-08 10:51:28 IP:203.79.xxx.xxx 訂閱
看了一下你的程式,主要的 DB 運作應該是在  DoBeforeProcessed 跟 DoAfterProcessed
但實際上還是不太清楚這兩個procedure的內部動作為何?

而你說的 thread執行在一個迴圈中,會持續跑很長的時間,因此不存在“太久沒有做動作”這個問題 ,我再跟你解釋一下

Thread 的迴圈是無窮迴圈,除非你下 Terminated =true 才會結束,但不代表在迴圈內的 Connection 就一定會有動作。

我舉個實際的例子
[code cpp]
while not query1.eof do
begin

while not query2.eof do
begin
query2.next;
end;

query1.next;
end;
[/code]

當上面的例子,如果 query1 與 query2 屬於兩個不同的connection 時,而query2 的迴圈運作時,其實query1的connection 是『沒有動作』的....

當query2的迴圈跑超過一定時間後,DB會主動把query1 的 connection 砍掉,
而query2跑完時,它就會去跑 query1.next; , 而此時就會有 Exception 跑出來了。

但整個 process 是在一個大迴圈中跑,也就是你講的 thread執行在一個迴圈中,會持續跑很長的時間

但不保証所有的 Connection 是一定『有動作』的。


以上說明,請參考








===================引 用 dust.zhu 文 章===================
感謝carstyc的回復
datamodule中有對應線程的database,session且每個線程只有一對;database.sessionname:=Session.sessionname,
thread執行在一個迴圈中,會持續跑很長的時間,因此不存在“太久沒有做動作”這個問題
線程的邏輯大概如下,這個線程的tquery是自動創建,其它兩個線程引用了datamodule中的tquery


[code delphi]
procedure TPTSThread.Execute;
const
C_SECOND = 1 / 8640;//10s
begin
{ Place thread code here
}
try
try
{建立線程和ADO組件的關系(線程中有用到一個自動創建的ado組件,
僅用于讀取本地access database中的數據)}
CoInitialize(nil);
//初始化系統參數
IniParameters;
while True do
begin
try
if FNextProcessTime < Now then
begin
//如果線程中止,跳出循環
if Terminated then
Break;
//當前此指針函數為空;DoBeforeProcessed:=nil;
if Assigned(DoBeforeProcessed) then
Synchronize(DoBeforeProcessed);
//check Process執行的條件是否滿足
if CheckInputs then
begin
//如果線程中止,跳出循環
if Terminated then
Break;
{主處理邏輯;link sn,reel;扣減reel當前數量;如果reel數量耗完則下架,
如果此reel有接料(備用reel),上架接料reel(參與link sn,reel,扣減數量)
此邏輯用的tdatabase來源于datamodule,在線程create時作參數傳入;
其它所有的tquery全部在線程create內部自動創建}
Process;
end;
FNextProcessTime := NOW C_SECOND;
//當前此指針函數為空;DoAfterProcessed:=nil;
if Assigned(DoAfterProcessed) then
Synchronize(DoAfterProcessed);
//如果線程中止,跳出循環
if Terminated then
Break;
end
else
Sleep(C_MILLISECOND);//等待200毫秒;釋放cpu
//如果線程中止,跳出循環
if Terminated then
Break;
except
on e: Exception do
begin
FUserMessages := e.Message;
//如果有出現“ora-...”等database連接的錯誤,close database
if IsDBException(FUserMessages) then
FDBOracle.Close;//此處FDBOracle引用了datamodule中的database
//顯示給用戶系統異常信息,不需要用戶確認
FDialogType := dtNoDialog;
Synchronize(MessagesToUser);
end;
end;
end;
except
on e: Exception do
begin
//顯示給用戶系統異常信息,需要用戶確認
FUserMessages := e.Message;
FDialogType := dtConfirmDialog;
Synchronize(MessagesToUser);
end;
end;
finally
//釋放資源
FreeResource;
CoUninitialize;
end;
end;
[/code]
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#13 引用回覆 回覆 發表時間:2009-07-08 11:10:34 IP:221.224.xxx.xxx 訂閱
感謝carstyc及時回復
DoBeforeProcessed,DoAfterProcessed在當前的程序中邏輯為空,并沒有用到
Process中包含了數據處理的全部主邏輯;不只本機緩存dataset的利用,也包含了insert,delete,update,所以每10S左右connection一定會被使用

我們近期做了些測試;當連接database數據作業頻繁的時候,時間長了就會出現錯誤;當數據交易量增大到每s成百上千筆的時候,一旦出錯,90%的情況下connection就不能再被使用(即使關閉再開啟),除非整個application關閉
編輯記錄
dust.zhu 重新編輯於 2009-07-08 11:18:21, 註解 無‧
dust.zhu 重新編輯於 2009-07-08 11:21:05, 註解 無‧
carstyc
資深會員


發表:16
回覆:254
積分:329
註冊:2003-07-18

發送簡訊給我
#14 引用回覆 回覆 發表時間:2009-07-08 11:48:54 IP:203.79.xxx.xxx 訂閱
sorry  , 漏看了一個 process

但你的 befroeprocessed 跟 afterprocessed 都有使用 Synchronize ,為啥單 process 沒有用 Synchronize 呢。

你要不要試看看吧 process 用 Synchronize 去執行。

雖然你的 Thread 應該是唯一的,但習慣上用到 vcl 的 TDatabase 跟 TSession ,還是習慣把它包起來,執行上應該會比較穩定。

另提供幾個作法你試看看

1. process 處理完成後,把 database close ,待下次又執行到process 時,才去把database開啟

2.用 Synchronize 去執行process

3.不要用 DataModule 的 Database ,直接在 Thread 的 Constructor 中去建立 TDataBase 及Session及所有的TQuery。




===================引 用 dust.zhu 文 章===================
感謝carstyc及時回復
DoBeforeProcessed,DoAfterProcessed在當前的程序中邏輯為空,并沒有用到
Process中包含了數據處理的全部主邏輯;不只本機緩存dataset的利用,也包含了insert,delete,update,所以每10S左右connection一定會被使用

我們近期做了些測試;當連接database數據作業頻繁的時候,時間長了就會出現錯誤;當數據交易量增大到每s成百上千筆的時候,一旦出錯,90%的情況下connection就不能再被使用(即使關閉再開啟),除非整個application關閉
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#15 引用回覆 回覆 發表時間:2009-07-09 11:33:30 IP:221.224.xxx.xxx 訂閱
感謝carstyc的答復

由于Process是一個非常耗時的作業,如果用Synchronize(Process),thread將suspend,main thread將執行process邏輯,
這將導致界面freeze,用戶無法作業;
鄙人認為只有耗時非常短,且又和其它thread或main thread有資源共用的邏輯,才可用Synchronize,即可保證資源的安全性又不影響用戶
delphi幫助文檔有如下
“Data access components are thread-safe as follows: For BDE-enabled datasets, each thread must have its own database session component. The one exception to this is when you are using Access drivers, which are built using a Microsoft library that is not thread-safe. For dbDirect, as long as the vendor client library is thread-safe, the dbDirect components will be thread-safe. ADO and InterbaseExpress components are thread-safe.
When using data access components, you must still wrap all calls that involve data-aware controls in the Synchronize method. Thus, for example, you need to synchronize calls that link a data control to a dataset by setting the DataSet property of the data source object, but you don抰 need to synchronize to access the data in a field of the dataset”
并沒有提到BDE是thread-safe,據我們近期的測試結果,開啟三個application,每個application開一個thread;運行一段時間,程序同樣會出問題
編輯記錄
dust.zhu 重新編輯於 2009-07-09 11:58:28, 註解 無‧
carstyc
資深會員


發表:16
回覆:254
積分:329
註冊:2003-07-18

發送簡訊給我
#16 引用回覆 回覆 發表時間:2009-07-09 12:23:53 IP:203.79.xxx.xxx 訂閱
你說的沒錯,只有Thread在存取 Thread non safe 資源時,用Synchronize才可保證資源的安全性 。
不過這只是我好奇你的 process 沒有用 Synchronize 執行而已,不一定問題是發生在這點上面。

但你的問題,看起來就很像是 Connection 突然不見的樣子。

你現在需要的是先找出 Exception 的原因,找到原因再來針對問題點解決。

那你可以試看看,試著去 監看你 DB 上的 connection ,當你AP執行起來時,應該就會產生一個 Connection ID,你把 ID 記起來,然後當程式發生異常時,再去看一下 Connection ID 是否還存在,還是不見了。如果你的 AP 的 database 不會中途 close 的話,你的 connection ID 應該是不會變。

所以你可能需要另一個程式定時去撈取DB上的 connection information ,並紀錄供後續追蹤用。

先提供你另一個暫時解決方案,你之前有提到,若發生異常,即使 Database重新啟用也無法work,必需重啟 AP

如果暫時找不到問題解決方式的話,就用 flyup 大大 提供的方法,在你偵測到Exception 時,重新啟動自己 AP
http://delphi.ktop.com.tw/board.php?cid=30&fid=72&tid=26009






===================引 用 dust.zhu 文 章===================
感謝carstyc的答復

由于Process是一個非常耗時的作業,如果用Synchronize(Process),thread將suspend,main thread將執行process邏輯,
這將導致界面freeze,用戶無法作業;
鄙人認為只有耗時非常短,且又和其它thread或main thread有資源共用的邏輯,才可用Synchronize,即可保證資源的安全性又不影響用戶
delphi幫助文檔有如下
“Data access components are thread-safe as follows: For BDE-enabled datasets, each thread must have its own database session component. The one exception to this is when you are using Access drivers, which are built using a Microsoft library that is not thread-safe. For dbDirect, as long as the vendor client library is thread-safe, the dbDirect components will be thread-safe. ADO and InterbaseExpress components are thread-safe.
When using data access components, you must still wrap all calls that involve data-aware controls in the Synchronize method. Thus, for example, you need to synchronize calls that link a data control to a dataset by setting the DataSet property of the data source object, but you don抰 need to synchronize to access the data in a field of the dataset”
并沒有提到BDE是thread-safe,據我們近期的測試結果,開啟三個application,每個application開一個thread;運行一段時間,程序同樣會出問題
編輯記錄
carstyc 重新編輯於 2009-07-09 12:24:32, 註解 無‧
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#17 引用回覆 回覆 發表時間:2009-07-12 00:28:00 IP:118.167.xxx.xxx 未訂閱
這個文檔大致上是說資料存取元件是俱備「Thread-safe」的,除了存取M$的ACCESS以外(主因在ACCESS的Driver上)。

所以如果是使用BDE元件的話,應該就可以不用考慮這方面的問題,除非真的有BUG。(但好像沒人沒應過這方面的問題)

既然有用到ACCESS,那要不要先將存取ACCESS的部份先取消呢?
這樣的話同步功能應該就可以取消了吧。

===================引 用 dust.zhu 文 章===================
由于Process是一個非常耗時的作業,如果用Synchronize(Process),thread將suspend,main thread將執行process邏輯,
這將導致界面freeze,用戶無法作業;
鄙人認為只有耗時非常短,且又和其它thread或main thread有資源共用的邏輯,才可用Synchronize,即可保證資源的安全性又不影響用戶
delphi幫助文檔有如下
“Data access components are thread-safe as follows: For BDE-enabled datasets, each thread must have its own database session component. The one exception to this is when you are using Access drivers, which are built using a Microsoft library that is not thread-safe. For dbDirect, as long as the vendor client library is thread-safe, the dbDirect components will be thread-safe. ADO and InterbaseExpress components are thread-safe.
When using data access components, you must still wrap all calls that involve data-aware controls in the Synchronize method. Thus, for example, you need to synchronize calls that link a data control to a dataset by setting the DataSet property of the data source object, but you don抰 need to synchronize to access the data in a field of the dataset”
并沒有提到BDE是thread-safe,據我們近期的測試結果,開啟三個application,每個application開一個thread;運行一段時間,程序同樣會出問題
dust.zhu
一般會員


發表:3
回覆:8
積分:2
註冊:2009-06-30

發送簡訊給我
#18 引用回覆 回覆 發表時間:2009-10-22 16:56:27 IP:221.224.xxx.xxx 訂閱
好久無法進入這個論壇了,剛開始以為論壇關閉了或被大陸給和諧了!
想想純技術的論壇,應該不至于遭此下場,經過多方搜索,才發現改成HTTPS了,呵呵!
------------------------------------------------------------------------------------------------------------
現在問題已經解決,經過一段時間的運行,再沒有發現錯誤!

此前確實讓我郁悶了好長時間,一直找不到解決的方法,上面又盯的緊,最后下了決心,把有關dababase操作的三個線程合成了一個,經過一段時間的log觀察,終于發現了問題所在
PTS線程中有一種消息必須要用戶確認,確認后才能繼續執行,如果用戶半小時或一個小時后確認,后續的database操作就會報錯;這種情況應該屬于database正常關閉connection
所以database server上看不到exception log,了解到這點就好辦了,如果用戶在規定時間內沒用確認消息,系統自動取消確認動作,以繼續執行

其它存在的問題
socket錯誤:如果在不同的線程里使用FTP,及其它的網絡協議函數,極有可能引發這種錯誤,可以用臨界區或合并線程解決;而且這種錯誤一發生可能會引發BDE的錯誤(這點未做驗證)

個人的一點總結:
如非特殊需要,盡量不要開多個子線程,既浪費database的connection資源,又會導致程序異常復雜,出了問題很難調試!

最后,鄙人十分感謝各位的回復,
特別感謝carstyc,您的回復切中要害!
謝謝!


編輯記錄
dust.zhu 重新編輯於 2009-10-22 17:01:39, 註解 無‧
dust.zhu 重新編輯於 2009-10-22 17:04:15, 註解 無‧
系統時間:2024-04-26 14:44:38
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!