最近在开发一个网络程序,突然想到一种极端情况:
比如客户端给服务端发送一个commit 命令,
我主观猜测流程应该是:
客户端调用write往套接字写commit命令,oracle服务端收到commit命令后执行提交,同时反馈给客户端commit的结果,此时假如网络突然中断了。客户端收不到服务器发送的反馈消息,而服务段又提交了事务。这样可能会造成客户端再次执行一个之前的命令,有可能造成数据重复提交了。有没有哪位高人了解oracle事务的处理机制的,麻烦给解惑一下,谢谢。

解决方案 »

  1.   

    重复提交?
    如果一个事务已经提交,再次执行commit也没有关系啊。
      

  2.   

    回楼上的,我说的这种情况是oracle服务端已经更新了,但在返回给客户端commit结果时网络突然闪断。
    比如:
    update t set t.a = t.a+2;
    commit;执行commit之后网络闪断,客户端认为没有更新成功,再次执行一下上面的语句,会造成重复更新。
      

  3.   


    就是说,应用没有接收到成功提示,就会直接再运行一次你的这段脚本?
    LZ制订的应用程序是这个规则吗?
    从服务器上来说,commit就commit了,否则就会rollback。
    导致之前的事务中所有dml操作回滚。
      

  4.   

    我想如果出现这种情况,应该是通过异步IO来解决的。如果是同步I/O,当一个I/O操作执行时,应用程序必须等待,直到此I/O执行完. 相反,异步I/O操作在后台运行,I/O操作和应用程序可以同时运行。oracle的commit主要工作就是把redo log buffer中的内容写到redo logfile文件中,当客户端发出commit命令之后,只要接受到服务器端一个“我已收到commit请求”的信息,就会马上提醒用户,commit操作已经完成。而不用等到服务器端将事务的redolog缓冲区信息写到log文件之后再返回“commit成功”的信息。这样用户得到响应的时间就变得非常短,在这段时间内出现网络故障的几率就更低。至于用户发送commit到接受到服务器的提示信息这段时间内发生网络故障,这个是神仙也解决不了的问题。