逻辑:
MQ发送->更新Process_code->更新process_code正常->MQ.commit()
|->更新Process_code异常->MQ.rollback()
程序大概:
MQ.Send();
Connection conn=ConnectionPool.open();
if(conn!=null){
try{
conn.setAutoCommit(false);
//Execute SQL Strings on conn
//更改process_code
...
conn.commit();//
MQ.commit();
}
catch(SQLException ex){
//conn.rollback
//MQ.rollback();更Process_code失败,mq发送也rollback
...
}
}
一般的情况下这样是没问题的,但如果这个捕获的ex是调用commit()时产生的 "Connection Closed"异常
所执行的SQL语句是否已经生效呢??
这时候程序实际是进入了不确定的状态
Connection.commit()这样的方法逻辑上应该算原子操作,但是它是不可靠的,因为网络是不可靠的,所以永远无法保证数据库操作的commit和jdbc客户端收到这个确认在一个事务里面
不知道这算不算jdbc的一个bug?(虽然这是所有网络程序无法避免的)
=========================================
出问题的原因:
我在用Oracle数据库的时候发现虽然commit抛出"Connection Closed"异常,但所执行的SQL语句(更改Process_code为2)已经生效了,程序处于不确定的状态!这样我就根本无法根据catch到的异常判断做下一步操作(是MQ.rollback,还是MQ.Commit),原来认为出现SQLException就MQ.rollback();结果出现了process_code=2而数据没有发送的情况
=========================================
解决办法:
这个异常是一个随机出现的异常,通过查看日志发现在将近两个月的测试期间仅出现过一次,保守估计此期间数据传输总条数大于40万条,(每条数据传输有多条connection.commit();)
如果出现异常,可以多尝试几次,只要有一次commit成功,程序就可以正确得运转下去,只有当连续几次Connection.commit()出现异常时,程序才会处于不确定得状态,这时认为process_code更新失败,MQ.rollback()