sybase 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:

chained
begins a transaction just before the first data retrieval or data modification
statement at the beginning of a session and after a transaction ends. In
chained mode, Adaptive Server implicitly executes a begin transaction
command 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 on
2> go
1> set chained on
2> go
1> begin tran
2> go
1>

  似乎多次调用 set chained 并不会产生异常。接下来,

1> set chained on
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1> set chained off
2> go
Msg 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 on
2> go
1> select 1
2> go

-----------
1

(1 row affected)
1> set chained on
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1> set chained off
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1>

  在执行 select 1 之前,数据库自动启动了一笔事务,因此不能再执行 set chained。接下来,完成隐式启动的事务:

1> rollback
2> go
1> set chained off
2> go
1>

  二、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() 方法回到池中时,未能恢复到初始状态 (即 chained off),则应用多次获取该连接并进行一定操作后,就很有可能出现异常。见下图:

  通过上面的分析,理解了产生此异常的原因,就很容易避免此异常,即在完成事务后,关闭连接前,显式地调用 setAutoCommit(true)。或许有的程序员会认为麻烦,但别忘记“完壁归赵”是资源借用者的义务。

max-chained-neighbor-updates是一种算法或方法,可以用于优化网络中的更新操作。在一个网络中,节点之间的相互关系往往会发生变化,这可能导致一些更新操作需要在节点之间传递。传统的更新方法是一次性地在整个网络中进行更新,但这可能会造成网络拥堵和延迟。 max-chained-neighbor-updates通过将更新操作切分成多个步骤,并根据节点之间的连接关系,逐步地将更新从一个节点传递到另一个节点。具体来说,它将更新操作限制在每个节点的邻居节点之间传递,而不是在整个网络中传递。当一个节点完成更新后,它将通知它的邻居节点进行更新,然后邻居节点再通知它们的邻居节点,依此类推。这样的传递可以形成一个链式的更新流程,使得更新操作在网络中以最大化的效率进行传递。 使用max-chained-neighbor-updates方法的好处是可以减少网络拥堵和延迟。因为每个节点只需要与它的邻居节点进行通信,而不需要与整个网络进行通信,节省了网络资源和通信成本。此外,逐步传递更新可以避免大量的更新同时传递,减少了传输冲突和数据错误的可能性。 然而,max-chained-neighbor-updates也有一些限制。首先,它仅适用于节点之间具有明确定义的连接关系的网络。其次,如果一个节点的邻居节点在进行更新之前已经开始了更新操作,可能会导致更新顺序的混乱和错误。因此,在实施max-chained-neighbor-updates时需要考虑这些问题,并采取适当的措施来确保更新操作的正确性和一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值