象其他數據系統一樣SQL Anywhere在執行sql語句的時候會維持一個db handle,當語句結束調用結束后釋放這個handle.我們在開發過程成往往會忘記去釋放這個handle或者異常發生后沒有對它進行有效的處理,而造成超出連接級數據庫屬性Max_statement_count 的設定值,進而引起數據庫拋錯誤信息.接下來就這個問題進行分析.
一、如何做到始終釋放open的handle
在處理db的框架中每個處理函數都應該象下面一樣處理
try
{
//execute sql
}
catch(...)
{
}
finally
{
//handle dispose codes snippet
}
二、如何通過配置db啟動選項來找到你犯的錯
sybase提供了一些很好的啟動參數可以讓你抓出你想要的sql log,這里我只介紹 -zr 和 -zo
1.-zr
語法:
-zr { all | SQL | none | SQL+hostvars } ...
可取值 ALL、SQL、NONE 或 SQL+hostvar。ON 和 ALL 是等效的。OFF 和 NONE 是等效的。此調用對發送到數據庫服務器的各 SQL 語句啟用日志,以便用于疑難解答,此選項同數據庫服務器選項 -zr 和 -zo 一起使用。
如果將 -zr設置為 OFF,則會關閉請求日志文件。
如果選擇 SQL,則僅記錄以下類型的請求:
START DATABASE
STOP ENGINE
STOP DATABASE
語句準備
語句執行
EXECUTE IMMEDIATE 語句
選項設置
COMMIT 語句
ROLLBACK 語句
PREPARE TO COMMIT 操作
連接
斷開連接
事務開頭
DROP STATEMENT 語句
游標解釋
游標關閉
游標重新開始
錯誤
將 -zr 設置為 SQL+hostvar 時將在日志中輸出 SQL和 主機變量值。
使用 property('RequestLogging') 可以得到 -zr 設置的當前值。
2.-zo
語法:
-zo filename...
將請求記錄信息重定向到與常規日志文件不同的文件中
三、通過得到的log文件得到你未釋放的handle

log 片斷
1
+1,<,2,PREPARE,SELECT * FROM Temp
2
+3,>,2,PREPARE,131267
3
+22,<,2,OPEN,131267
4
+23,>,2,OPEN,65732
5
+6,<,2,COMMIT
6
+1,>.,2
7
+11,W,2,100,Row not found
8
+58,<,2,CLOSE,65732
9
+1,I,2,1,1,0,NOSCROLL*+READONLY+HOLD
10
+1,>,2,CLOSE
11
+3,<,2,COMMIT
12
+1,>.,2
13
+37,<,2,DROP_STMT,131267
14
+1,>,2,DROP_STMT
每一個handle必須經過Prepare->Drop_Stmt這個過程,而如果我們在代碼中忘記釋放handle的話log中是不會有對應的DROP_STMT語句的。
可以通過Prepare后的句柄號來查找對應的DROP_STMT語句(如代碼中的第2行和第37行),如果沒找到的話那可以查看對應的sql語句從而找到對應的代碼。
整理的比較倉促,如有考慮不周指出請幫我指出。同時希望這篇文章對你有所幫助。