在记录锁上有SQL UPDATE抛出错误消息,就像本机IO一样

时间:2017-09-01 19:57:01

标签: sql db2 ibm-midrange db2-400 rpgle

我对IBM i有点新,我来自Java / C#背景。所以,如果我使用错误的术语,请纠正我。我们目前使用的是IBM i 7.1,并将在明年内转向7.3。

我的任务是更新文件中的记录。我在这里写了两个RPGLE程序来做同样的事情。

原生I / O:


    **free
    dcl-f table1 usage(*update) keyed;
    setll ('001': 'Y') table1;
    reade ('001': 'Y') table1; 
    dow not %eof(table1);
        letter = 'X';
        update table1;
        reade ('001': 'Y') table1;
    enddo;
    *inlr = *ON;
    return;

嵌入式SQL:


    **free
    exec sql UPDATE table1 
            SET letter = 'X'
            WHERE GroupCode = '001' AND Newbie = 'Y';
    *inlr = *ON;
    return;

在我看来,这是SQL与原生I / O相比具有强大优势的时代之一。

这是我的问题。我的公司依赖于CPF消息。像许多公司一样,我们并不完美并拥有遗留代码。有相当多的,有时我们得到记录锁。发生这种情况时,会向系统发送一条错误消息,并等待某人登录并回答。

这导致调用我们的内部支持,并且通常在有人访问它时,锁定文件的程序完成,我们只需要回答R重试,并且更新继续从中断。这种情况并不经常发生,以至于我们可以花时间来修复调度过程以及所有程序的记录锁定,但通常情况下,没有这种能力会导致我们大量的痛苦。

使用本机I / O会抛出这些消息。使用嵌入式SQL,SQLSTATE和SQLCODE变量已设置,程序将继续,而不向系统发送任何消息。我可以检查这个变量,编写我自己的消息,并在出现问题时向系统发送消息。然而;这不太理想。如果我手动提供重试选项,则无法从停止的位置恢复更新。我必须再次运行整个更新语句。

我已经查看过编译器选项,控制选项,sql选项和sql命令,而且我所看到的没有一个让我能够找到它的能力。

简而言之,我想知道,有没有一种方法可以让嵌入式SQL在不受监视的错误消息上表现得像本机I / O一样?

5 个答案:

答案 0 :(得分:1)

简而言之......不。

SQL是一种不同的范例。 DB2 for i中的SQL错误处理就像SQL中的任何其他语言的错误处理一样......

您可能希望在承诺控制下运行UPDATE。然后检查sqlstate。如果没有错误,COMMIT交易。

否则,ROLLBACK交易,并显示您的消息。此时,重试选项将循环返回并重新发出SQL UPDATE

<强>的刊登
在你添加了所有这些之后,你的SQL版本看起来并不那么简洁吗?哎呀RPG版本实际上可以减少到5或6行...如果你想上学和使用输入主文件。不是说我现在推荐它。

RPG与数据库的紧密集成为您做了很多工作。 SQL很好,我一直都在使用它,但有时候更多的控制更好。值得庆幸的是,在IBM i上有SQL的替代品。

答案 1 :(得分:1)

更好的解决方案是捕获记录锁定错误并自动重试数据库更新操作,直到锁定消失,或在特定超时间隔后挽救。这可以通过本机I / O或SQL轻松实现,并且应该减少相当大比例的支持事件。

答案 2 :(得分:1)

我一直在野外看到这一点。不使用乐观代码。如果失败了,即使传统程序正在运行,也许乐观的编码就会超越它。

当行被锁定时,如何重做呢?导致过时编码技术问题的老游戏会用一条消息来锁定进程,因为他们所做的就是编写依赖于人为干预的代码。现在队列中的任何其他内容都被阻止,等待操作员回复消息的更多事情将会失败。

现代计划在未来失败时将能够重新安排自己。当进程重新安排时,可能会发送电子邮件。就像将来安排的可运行一样。

exec sql UPDATE table1 
        SET letter = 'X'
        WHERE GroupCode = '001' AND Newbie = 'Y' 
     and letter <>  'X';   /*  and letter <> 'X' is the optimistic part */
*inlr = *ON;
return;

if calledpgm failed then reschedule to run in the future send an email to support if desired.

答案 3 :(得分:1)

如果您寻找完全改变方法的解决方案,可以有很多方法。仅在一个特定路径上(仅使用本机或仅使用sql等)缩小选项范围。
我试着看看上面的不同答案,这是我的观点   - 使用danny117的方法,如果没有依赖于“时间”,文件字段'字母'可以更新为'x'然后在'监视器'内部更新sql并让整个程序运行带有过滤器的多个计划在letter ='x'上可以是一个选项
  - 对于jmarkmurphy的方法,但等待取决于文件属性,如果文件在外面锁定较长时间可能会有问题。
  - 因为即使查尔斯选项也没有帮助偶尔锁定和释放

  - 我正在考虑另一种选择,如果更新运行速度快于其他程序将锁定文件的持续时间。为此更新“专门”分配文件,并在成功更新后将其释放。在分配循环期间,延迟步骤直到你获得文件的独占锁定,然后更新。

答案 4 :(得分:0)

在这种情况下你可以:

**free
dou sqlstate = '00000' or sqlstate = '02000';
  exec sql UPDATE table1 
          SET letter = 'X'
          WHERE GroupCode = '001' 
            AND Newbie = 'Y'
            and letter <> 'X';
enddo;
*inlr = *ON;
return;

锁定仍会在SQL中等待60秒左右,具体取决于文件的WAITRCD属性或覆盖,因此这不会造成太大的问题。

您还可以创建一个过程,以便在锁定的情况下发送消息并将其实现为:

**free
dou sqlstate = '00000' or sqlstate = '02000';
  exec sql UPDATE table1 
          SET letter = 'X'
          WHERE GroupCode = '001' 
            AND Newbie = 'Y'
            and letter <> 'X';
  if sqlstate = '57033';
    SendSqlMsg('SQL0913');
  endif;
enddo;
*inlr = *ON;
return;

您甚至可以让该程序发送查询消息并检索回复。然后根据需要处理回复。我将把它作为练习留给你。