ProC血的教训之二!游标使用完关闭之后最好释放!

本文通过排查网络连接问题,发现程序崩溃是由未正确释放游标导致的。详细介绍了如何定位问题,并给出了通过设置RELEASE_CURSOR=YES来释放游标的解决方案。

在经历上一个教训并解决问题之后,本以为可以高枕无忧了,结果又遇到一个问题,在多次拔插网线之后,程序运行到fetch cursor的时候就崩掉了,任何信息都没有提示。我确定是上下文的问题,但是怎么也改不好,我的程序没有用到多线程,而且reconnect之前也都关闭数据库连接了,为了确定使用全局上下文,我在每个函数开始的地方加了EXEC SQL CONTEXT USE DEFAULT这句,还是在EXEC SQL处崩溃!又花了我半天的时间,终于找到原因。

在最后时刻,我想,为什么这次出现问题的总是游标?而且总是在fetch的地方?为什么declare 游标没问题,open也没问题?我在fetch游标之前加了一句普通的SQL,发现是没问题的,这更加让我确定是游标的问题。可是开始游标是可以正常执行fetch的啊,我每次都declare-->open-->fetch-->close,对了,程序每次都declare,这不是重复声明吗?为什么之前没有问题,close对应的貌似是open,declare的时候或许是这样的,如果没有这个游标就创建,有的话就使用原来的,难道declare对应的还有一个反操作?我能想到的就是销毁或者就是RELEASE,于是网上一搜,还真有,是我基础不扎实,关键在下面这段话:


关于游标的释放

在一个连接中,若该连接引用记数为1,则关闭该连接也释放游标;如在同一个进程中打开连接,操作数据,关闭连接。

若连接记数大于1,如父进程打开连接,子进程共享该连接进行操作,则连接记数大于1,子进程不能做关闭连接操作。此时要释放一个游标,在关闭游标后,还必须做commit或rollback;此外,还要设置release_cursor选项为yes,设置方法是在proc命令行中增加release_cursor=yes,或在程序中编写:

EXEC ORACLE OPTION(RELEASE_CURSOR=YES);  

否则不能释放,最终会报-1000错:maximum open cursors exceeded。

我有点明白了,declare的游标也是与数据库连接或者上下文绑定的,如果没有释放的话,这个游标还是存在的,那么当程序连接换到另一个时,使用游标却还是在原来的那个连接上,所以可能会导致莫名奇妙的错误。于是我在游标close之后加了

EXEC ORACLE OPTION(RELEASE_CURSOR=YES),经过测试,没有再出现程序崩溃的问题。
因此,在程序可能会使用多个数据库连接的情况,游标使用完最好要释放。

### PROC main() 的含义及代码添加方法 在 RAPID 编程语言中,`PROC` 是用于定义过程(Procedure)的关键字。`PROC main()` 是一个特殊的过程名称,表示主程序入口点。当机器人运行任务时,`main()` 过程会被优先执行[^1]。通常,`main()` 中包含初始化设置、调用其他子程序或执行主要逻辑的代码。 以下是一个典型的 `PROC main()` 定义示例: ```rapid PROC main() ! 初始化设置 SetSpeed 50; ! 设置速度为 50% SetTool tGripper; ! 设置工具坐标系为 tGripper SetWObj wObject_1; ! 设置工件坐标系为 wObject_1 ! 调用其他子程序 Path_130(); ! 调用路径规划子程序 Task_200(); ! 调用任务子程序 ! 结束操作 StopAll; ! 停止所有运动 ENDPROC ``` - **解释**: - `SetSpeed`:设置机器人的运行速度。 - `SetTool`:指定当前使用的工具坐标系。 - `SetWObj`:指定当前使用的工件坐标系。 - `Path_130()` 和 `Task_200()`:调用其他已定义的子程序。 - `StopAll`:停止所有机器人动作。 #### 如何在 PROC main() 中添加代码 要向 `PROC main()` 中添加代码,可以按照以下方式操作: 1. **初始化设置**:在主程序开始部分添加必要的初始化代码,例如设置速度、工具坐标系和工件坐标系。 2. **调用子程序**:通过子程序名称调用其他已定义的过程,例如 `Path_130()` 或 `Task_200()`。 3. **添加逻辑控制**:根据需求添加条件判断、循环或其他逻辑控制语句。 4. **结束操作**:在主程序末尾添加清理或停止操作的代码。 以下是一个扩展示例,展示如何在 `PROC main()` 中添加复杂逻辑: ```rapid PROC main() ! 初始化设置 SetSpeed 80; SetTool tGripper; SetWObj wObject_1; ! 条件判断 IF io_Sensor = 1 THEN Path_130(); ! 如果传感器信号为 1,则执行路径规划 ELSE Task_200(); ! 否则执行任务子程序 ENDIF ! 循环操作 FOR i := 1 TO 5 DO MoveJ Target_Start, v1000, z10, Tool_1\WObj:=WorkObject; Delay 2; ! 每次循环延迟 2 秒 ENDFOR ! 结束操作 StopAll; ENDPROC ``` - **解释**: - `IF` 和 `ELSE`:实现条件分支逻辑。 - `FOR` 和 `ENDFOR`:实现循环操作。 - `Delay`:添加延迟时间。 #### 注意事项 在编写 `PROC main()` 时需要注意以下几点: - 确保主程序逻辑清晰且易于维护。 - 避免在主程序中直接编写过于复杂的代码,建议将复杂逻辑封装到子程序中。 - 使用注释(以 `!` 开头)对代码进行说明,提高可读性。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值