今天看到一段代码对transaction object的DBParm赋值CommitOnDisconnect='No',本身这段代码没问题,pb transaction object 执行disconnect 命令断开与数据库连接时,如果不进行上面的赋值,pb会默认提交掉当前未提交的transaction。
但是看了这段代码的注释,立马傻眼了,注释是这样写的:
//==============================================================================
// 当一个较长的事务执行了前面几步尚未Commit时发生数据库连接断开(非法操作、断线、死机等)
// 此时会发生已执行的SQL不能回滚,从而导致数据错误(如库存已加但入库单却未打上入库标志)
// 为防止此类错误发生应设置为:数据库连接断开后不自动提交,即CommitOnDisconnect='No'
// Added By XXX 2002.09.10
//==============================================================================
从这段注释可以看出,作者的意思是,事务里面的sql语句集执行了一部分,出现非法操作、断线、死机等情况时,如果不设置CommitOnDisconnect='No',会出现执行了的sql语句commit,未执行的sql语句rollback的情况。实时真是如此吗?
我们在pb帮助文档中,可以找到这么一句话:
Automatic COMMIT when disconnected When a transaction is disconnected, PowerBuilder issues a COMMIT statement by default.
翻译过来是说,当transaction disconnected的时候,pb默认执行了commit命令。此处的disconnected 并不是我们广义上说的断开连接,他不包含网络断开,系统崩溃等特殊情况。这里说的disconnected 是执行disconnected命令。
自己多想想也能明白的,网络都断开了,数据库服务端怎么可能收到pb客户端发送的commit命令,有的人说了,这个是作为连接参数传给数据库的,数据库会知道这个参数,当网络断开时,数据库端自动提交,我只能说这些人想得太天真了,pb几乎可以连接所有关系型数据库,pb有什么能力要求所有关系型数据库厂商按照他们传过来的参数要求,当网络断开时,执行commit或者rollback。
有的人又要反驳了,说pl/sql执行一句sql命令,不手动commit,退出pl/sql会自动commit,这难道不是数据库服务端判断的?这个还真不是数据库服务端判断的,pl/sql工具菜单->首选项->oracle->连接->注销(有打开的事务),从这里可以看到,这里默认设置了commit。
所以说当disconnected时,到底要不要commit是客户端决定的,如果需要commit,客户端就需要默认发送一个commit命令。这里说的disconnected是正常的系统断开,并不包含网络断开,系统崩溃的异常情况。