【转】 Sybase ASE 编程常见问答
来源:互联网 发布:编程命名规则 编辑:程序博客网 时间:2024/06/04 18:50
Sybase ASE 编程常见问答
转自:http://www.sybaseclub.org/twiki/bin/view.cgi/ASE/ASEProgrammingFAQ
如何锁定一条记录jConnect 中 Statemnt 的注意事项jConnect 与 Scrollable Cursor理解 SET CHAINED command not allowed within multi-statement transaction.如何让 jConnect 支持超过 255 的 Char或Varchar?
如何锁定一条记录
在开发中,经常会遇到需要锁定一条记录的情况,比如流水号生成器。在C/C++中,我们可以采用 OS 提供的并发控制机制,如信号量,来达到解决并发冲突的目的。ASE 没有明确给出这样的机制,但是可以利用 ASE 的一个特性来实现这个功能,即 ASE 在处理 update 语句时,会对符合条件的记录加锁,而并不检查这个 update 语句是否真的是要更新数据。
begin tran update Sequence set nextValue=nextValue where pk='value' // 实际不更新任何值 ..... do something update Sequence set nextValue=nextValue+1 where pk='value' commit/rollback
jConnect 中 Statemnt 的注意事项
- 显式地创建 Statement 及其子类对象;
错误的写法: ResultSet rs = conn.createStatement().executeQuery( sql ); ... rs.close(); 正确的写法: Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery( sql ); ... } catch ( SQLException ex ) { ... } finally { if ( rs != null ) rs.close(); if ( stmt != null ) stmt.close(); }
- 显式地关闭 Statement 及其子类对象;
- 显式地调用 Statement.clearWarning();
jConnect 与 Scrollable Cursor
jConnect 使用 TDS 协议与 ASE 数据库通信。低版本的 TDS 协议并不支持 scrollable cursor。为了支持 scrollable cursor,在调用 ResultSet? .next() 方法时,jConnect 在客户端对缓存所获取的数据行。显然,这有可能带来严重的性能问题。因此,应尽可能避免使用 TYPE_SCROLL_INSENSITIVE/TYPE_SCROLL_SENSITIVE 的结果集。当且仅当结果集较小时或者 ASE 15 及以上版本时,才使用 TYPE_SCROLL_INSENSITIVE/TYPE_SCROLL_SENSITIVE。
提示:ASE 15+ 支持 TDS Scrollable cursor,高版本的 jConnect (6.0+)会自动检查 ASE 是否支持 Scrollable cursor,并优先选择 native scrollable cursor,而不是在客户端做缓存。
理解 SET CHAINED command not allowed within multi-statement transaction.
在 Sybase ASE 实际应用中,特别是在 ASE + J2EE? 应用中,较容易出现 SET CHAINED command not allowed within multi-statement transaction.的异常(尽管到版本 15.0.1 为止,ASE 并不支持异常机制,但本文为了方便,统一采用“异常”一词)。有的开发人员认为这是 Sybase 数据库的问题;有的认为是多次调用 setAutoCommit() 方法的问题;有的开发人员则认为这是 jConnect 的问题,甚至从 jConnect 的代码上直接屏蔽此异常。
然而,SET CHAINED 异常倒底是怎样产生的?
一、数据库层
首先,让我们看看 set chained。下面的文字片段摘自《ASE 12.5.2 Reference Manual: Commands》,Page 430:
chainedbegins a transaction just before the first data retrieval or data modificationstatement at the beginning of a session and after a transaction ends. Inchained mode, Adaptive Server implicitly executes a begin transactioncommand before the following statements: delete, fetch, insert, lock table,open, select, and update. You cannot execute set chained within a transaction.
从此段文字可以得知,当 set chained on 后,delete、fetch、insert、lock table、open、select 以及 update 语句将自动启动一个事务,并要求显式的完成事务,即明确地调用 commit/rollback。同时,在事务中,不允许设置 chained 模式。
下面的 sql 代码片断将说明在数据库层上 SET CHAINED 错误信息是如何产生的。
1> set chained on2> go1> set chained on2> go1> begin tran2> go1>
似乎多次调用 set chained 并不会产生异常。接下来,
1> set chained on2> goMsg 226, Level 16, State 1:Server 'FLYBEAN', Line 1:SET CHAINED command not allowed within multi-statement transaction.1> set chained off2> goMsg 226, Level 16, State 1:Server 'FLYBEAN', Line 1:SET CHAINED command not allowed within multi-statement transaction.1>
显然,处于事务环境下,调用 set chained 是会发生异常的,这一点手册上也非常明确的指出了。但为什么前面的片断中两次连续调用 set chained 却不会产生异常呢?请注意文档上这一句:Adaptive Server implicitly executes a begin transaction command before the following statements: 。
重建一个数据库连接,从头开始:
1> set chained on2> go1> select 12> go ----------- 1(1 row affected)1> set chained on2> goMsg 226, Level 16, State 1:Server 'FLYBEAN', Line 1:SET CHAINED command not allowed within multi-statement transaction.1> set chained off2> goMsg 226, Level 16, State 1:Server 'FLYBEAN', Line 1:SET CHAINED command not allowed within multi-statement transaction.1>
在执行 select 1 之前,数据库自动启动了一笔事务,因此不能再执行 set chained。接下来,完成隐式启动的事务:
1> rollback2> go1> set chained off2> go1>
二、J2EE 层
J2EE 应用中,一些轻量级的数据访问层实现采用 Connection 的setAutoCommit(false) + commit()/rollback() 的方式来管理事务。通过对 jConnect 的反编译以及对 spt_mda 数据的分析,可以得知 setAutoCommit(true) = SET CHAINED OFF;setAutoCommit(false) = SET CHAINED ON,下图以顺序图展示调用 setAutoCommit() 方法时,实际发生的交互。
另一方面,J2EE 应用中大多采用了连接池。应用在调用 Connection.close() 方法时,实际上并没有真正地关闭连接,而是将连接回收到池中。假设连接的初态是 chained off。如果应用在取得连接后调用该连接的 setAutoCommit(false) 方法来启动事务,在未完成事务的情况下,通过 close() 方法回到池中,则当该连接下一次被取出并调用 setAutoCommit(false) 方法时就会抛出异常。见下图:
通过上面的分析,理解了产生此异常的原因,就很容易避免此异常,即调用了 setAutoCommit(false) 后,必须显示地完成事务,即使只是执行了一个select语句。同时,关闭连接前,应显式地调用 setAutoCommit(true)。或许有的程序员会认为麻烦,但别忘记“完壁归赵”是资源借用者的义务。
如何让 jConnect 支持超过 255 的 Char或Varchar?
url串中增加:JCONNECT_VERSION=6
- 【转】 Sybase ASE 编程常见问答
- 【转】 Sybase ASE Frequently asked questions (FAQ1)
- SYBASE ASE 常见配置探究及推荐值(完善中)
- Sybase ASE DBCC
- 学习sybase ase 12.5
- Sybase ASE 安装指南
- Sybase ASE的字符集
- Sybase ASE的字符集
- Sybase ASE的字符集
- Sybase ASE 临时表
- sybase ase 重启
- Sybase ASA 和 Sybase ASE 区别
- Sybase ase 数据库日常维护
- Sybase ASE的版本演变
- SYBASE ASE中的统计信息
- Sybase ASE各系统数据库
- sybase ASE 各版本说明
- 安装使用Sybase ASE 12.5
- 09年十大网络流行语英文版揭晓
- JAVA基础——XML解析
- Struts2中namespace引发的路径问题
- CVS更新时各种颜色的含义
- string 和stringbuilder的区别
- 【转】 Sybase ASE 编程常见问答
- 哪位朋友有汉文版的IPC标准?
- AIX 学习之旅
- 大淘宝的终极商业阶段
- 祝愿所有的老师教师节快乐~
- weblogic控制台密码的修改和恢复
- ubuntu创建、删除文件及文件夹,强制清空回收站方法(转)
- 样式表CSS中定义链接 A 的“爱恨原则”
- php中的SERVER变量