象其他数据系统一样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语句从而找到对应的代码。
整理的比较仓促,如有考虑不周指出请帮我指出。同时希望这篇文章对你有所帮助。