【问题标题】:Progress OpenEdge how to prevent someone from updating a record进展 OpenEdge 如何防止某人更新记录
【发布时间】:2016-03-29 08:38:35
【问题描述】:

我需要一种替代方法来阻止某人访问特定代码。

我会解释这个场景。

有两个程序。

在第一个程序中,最终用户创建形式发票。然后,当他/她查看发票上的详细信息时。该代码使用 EXCLUSIVE-LOCK 中的主表记录显示详细信息。这是为了防止其他最终用户在第一个用户忙于查看详细信息时更改任何内容。所以即使形式发票完成后也不能再更改。主表的记录仍处于 EXCLUSIVE-LOCK 状态。这是错误的,但它可以防止其他用户在第一个用户仍在忙于更新它时弄乱它。但是,在此程序中工作的人员将程序留在详细视图中。他们不出去。

问题是当第二个程序用于发送形式发票上的项目时。它使用同一个主表的记录。因此不能做任何事情,因为第一个程序仍然在 EXCLUSIVE-LOCK 中。

我的问题是……

如何防止用户在第一个程序中更改数据,就好像主表的记录在 EXCLUSIVE-LOCK 中一样,但实际上没有它在排他锁中?在多个会话中...

【问题讨论】:

    标签: updating progress-4gl openedge


    【解决方案1】:

    这可能是一个更好的评论,但我没有足够的声望点来制作 cmets。对不起。

    一些注意事项:

    1. 乐观锁定——如果它适合你的情况——几乎可以肯定是最好的解决方案。

    2. 如果您要向表中添加一个 isLocked 字段,您可能需要几个其他字段:

      • 记录被锁定的日期/时间 - 或者过期时间戳
      • Lo​​ckHolder -- 让您知道自己是否拥有它。
    3. 到期可以是自动的(如 cron 扫描),或者可以忽略,除非其他人想要记录。设置锁的程序也必须足够聪明,以检查它是否仍然持有它。事情变得复杂了。

    4. 有时不方便对表进行架构更改,或者需要更改的表太多。在这些情况下,您可以将这些字段添加到单独的 LockIt 表中。一个表可以为所有其他表处理这些锁。

    旁白:
    我们还将 LockIt 表用于另一个目的:确保一次只能运行给定程序的一个副本。 (通常这用于 cron 作业或批处理守护程序。)程序独占锁定 LockIt 表中的特定记录(但不会启动事务!),并且只要程序运行,它就会持有该锁。

    【讨论】:

    • 爱它。不幸的是,我和老板一起尝试了这个和上面的解决方案。他对两人都说不。无论如何我确实从中吸取了教训,所以谢谢大家。
    • 那么,你老板的要求是什么?这是另一种可能性:向保持记录锁定的程序添加自动超时。如果(比如说)30 分钟内没有活动;它可以退出。如果您真的想变得花哨,它甚至可以保存所做的任何更改——要么保存到表本身,要么保存到单独的跟踪表。如果有问题,可能会有解决方案;困难的部分有时是提出正确的问题。
    • 他希望它保持原样。毕竟我只需要确保程序中被阻止的所有内容都在按下 ctrl-c 时被撤消。我做到了。
    【解决方案2】:

    很可能,您的交易范围是错误的。我会继续假设您正在尝试在发票程序仍然打开的情况下进行调度。然后你不能,因为记录仍然被锁定。您的整个程序很可能是一个事务,只要屏幕正在运行,记录就会保持锁定状态。尝试重新访问您的更新,将您真正的更新操作包含在 DO TRANSACTION 块中,将一些 MESSAGE TRANSACTION 语句放在不同的地方,看看结果是什么。这将帮助您找到 Progress 被引导“相信”记录仍需要锁定的点。

    【讨论】:

    • 你说的很对。我已经在程序中找到了位置。在那些点上,记录只是被读取。不需要排他锁。该程序故意读取具有排他锁的记录,只是为了防止其他最终用户进入。------------- FIND FIRST "table" WHERE "blablabla" EXLCUSIVE-LOCK NO- WAIT NO-ERROR ==== > IF LOCK "table" THEN RETURN NO-APPLY ............这就是它的全部功能。所以我需要找到一种方法来阻止其他最终用户读取/更新而不阻止进程中的调度。
    • 在我目前工作的公司中,我们使用 AppServer,所以如果你知道它们是如何工作的,你就会知道我们不能持有锁。那么,我们所做的是有一个字段说明该记录已被锁定。因此,就像您提到的那样,其他用户在开具发票或发货时无法更改订单。如果您可以更改架构,则可以使用 char 或 boolean 字段。如果您不这样做,这实际上是最简单的解决方案,您必须将锁定的范围专门针对用户开具或修改发票记录时的点。
    • 这与我想到的解决方案相同。首先想确保这种事情不存在正在进行的事情。谢谢 bupereira...
    【解决方案3】:

    我假设您没有使用 appserver,因为在这种情况下,这种行为很可能不会成为问题。

    一种解决方案可能是改为“乐观锁定”方法。这意味着您从“NO-LOCK”开始,一旦您需要更改记录,您将锁定升级为 EXCLUSIVE-LOCK。这种方法可行,但您需要确保记录仍然存在并且未被其他用户更改。

    根据您的发票实际更改的频率,这可能(或可能不会)是一个解决方案。如果事故“偶尔”发生,这可能是一个可行的解决方案。如果它经常发生(每天左右),你需要做点别的。

    乐观方法的基本伪代码:

    FIND FIRST record WHERE somethingsomething NO-LOCK.
    
    /* Here goes code for displaying the record */
    /* .... */
    
    /* Here's the updates */
    IF userWantsToSave THEN DO:
        FIND CURRENT record EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
        IF AVAILABLE record THEN DO:
            IF CURRENT-CHANGED record THEN DO:
                MESSAGE "Changed!" VIEW-AS ALERT-BOX ERROR.
                /* Your code goes here */
            END.
            ELSE DO:
                /* Your code for updating goes here */
    
                MESSAGE "Success!" VIEW-AS ALERT-BOX INFORMATION.
            END.
        END.    
        ELSE IF NOT AVAILABLE record THEN DO:
            IF LOCKED record THEN DO:
                MESSAGE "Locked!" VIEW-AS ALERT-BOX ERROR.
                /* Your code goes here */
            END.
            ELSE DO:
                MESSAGE "Deleted!" VIEW-AS ALERT-BOX ERROR.
                /* Your code goes here */
            END.
        END. 
    END.
    

    Here's an example from the knowledgebase that goes more into depth with this.

    【讨论】:

    • 感谢您的意见。我非常喜欢乐观的方法。然而,这个特定的问题,在我们测试排他锁的时候,记录根本不应该在“EXCLUSIVE-LOCK”中。没有更新/添加/删除。它的唯一目的是阻止其他最终用户使用相同的程序获取相同的形式发票。手头的问题是,它阻止了在其他程序中使用相同记录的其他所有人,他们应该能够访问它。调度应该能够调度,而其他人不能在有人乱搞发票时忙着呢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多