【问题标题】:Preventing Users from Working on the Same Row防止用户在同一行上工作
【发布时间】:2010-09-19 07:57:12
【问题描述】:

我有一个类似于票务工作系统的 Web 应用程序在工作。一些用户输入新问题。其他工人选择并解决问题。所有数据都保存在 MS SQL server 2005 中。

致力于解决问题的用户会转到他们可以查看未解决问题的页面。因为最多可以有 20 人同时查看此页面,所以我必须解决的一个潜在问题是,如果有人在页面加载后选择了其他人选择的问题,会发生什么情况。

为了解决这个问题,我做了两件事。首先,显示要选择的问题的网格视图使用 AJAX 计时器每秒更新一次。一旦选择了一个问题,它最多会在一秒钟后消失。如果他们在这一秒内选择了一个,他们会收到一条消息,要求他们选择另一个。

问题在于其中的 AJAX 部分发送了太多更新(这是我的假设),并且影响了页面和数据库的性能。此外,更新并不是每秒都在执行。在触发存储过程时,我发现计时器不可靠。

必须有更好的方法,但我似乎找不到。有没有人遇到过这样的情况,或者有建议让多个用户不要选择相同的记录来维护?我真的不想完全禁用 AJAX 部分,因为我觉得单独的消息会使应用程序使用起来令人沮丧。

谢谢,

【问题讨论】:

    标签: asp.net sql-server vb.net ajax concurrency


    【解决方案1】:

    在数据库中的行上放置一个锁定时间戳字段。如果过期 timsetamp 早于特定时间,则编写一个返回 true 或 false 的存储过程。将您在 Web 应用程序上的会话设置为在同一时间(一两分钟)内到期。当用户选择一行时,他们点击了存储过程,这有助于应用决定是否应该让用户修改它。

    希望这是有道理的......

    【讨论】:

    • 我对你的方法没有太多经验,但我想我明白了。那么用户是否可能会尝试修改仍然被选中的记录?如果可能的话,我真正想做的是避免他们为选择不可用的记录而烦恼。
    • 那么,如果没有回发到服务器,如何隐藏它们?
    • 如果您检查时间戳并在两个彼此不是原子的不同事务中进行 SQL 更新,这是一个竞争条件......虽然我的猜测是这可能适用于类似 @ 987654321@.
    【解决方案2】:

    有两件事可以帮助缓解您的问题。

    首先,无论您的 ajax 更新时间框架如何,都需要在选择后通知该案例已被采纳。即使每秒检查一次也不意味着两个人不能在他们认为是同一时间点击同一个案例。在这种情况下,需要通知其中一位用户他们的选择是无效的,即使它在选择时看起来是有效的。此通知无需详细说明;即使在失望的情况下,保持轻松、有帮助的语气也可以改善用户的感知。而且,如果您已经确定了选择该记录的用户,那不仅会帮助您的用户在未来进行协调,而且还会将注意力从您的程序转移到蛇行的用户身上。 (实际上,管理层可能喜欢让您的用户偶尔发生冲突,因为这会促使他们更快地选择案例)

    其次,对您的案例显示方式进行小调整可以减少选择冲突。添加随机元素以显示顺序和/或过滤掉所有其他显示的案例将帮助您的用户自然地选择不同的案例。人类模式识别和任务选择并不是真正随机的,因此对表示的微小变化可能等于对选择行为的重大变化。减少碰撞机会使您的碰撞通知很少见(因此对您的用户来说不那么令人沮丧)。如果可以将您的用户分成有助于确定有用的案例排序/过滤的分类,那就更好了。

    好的,随着时间的推移,对您有帮助的第三件事是,您是否记录了碰撞发生的时间(包含有关碰撞的有用元数据,例如参与人员和选择时间)。借助可靠的碰撞数据,您可以找到有效的方法和无效的方法。随着时间的推移,您可以根据实际用例优化您的应用程序,并尽早发现潜在问题。没有什么比在他们意识到问题存在之前就已经解决问题(并且能够解释您解决问题的计划)更能让您的用户放心的了。

    使用这些缓解模式,您可能会发现可以安全地缩短 ajax 查询时间,而不会影响用户体验。通过有用的日志记录,您可以确保您所做的任何调整都确实有效(或无效——知道这可能更有用)。

    【讨论】:

    • +1 表示随机化,这正是我的建议!
    • 随机顺序无效。工单按服务级别到期优先级排序。
    • 服务等级过期的依据是什么?这是基于时间的决定吗?根据您的问题数量,您可以将它们分组到最近的一分钟(或十五分钟)并让它“足够好”。无论如何,我知道要求优先级的例外在政治上是有问题的,但如果你可以,它可能证明是值得的。
    • 输入问题时,几个字段确定优先级。这些级别每个都有计算服务时间的规则 - 营业结束、两个营业时间、48 小时等。基本上,我们应用此规则并将计算的日期时间与记录一起存储。由于 gridview 每秒都会更新以删除用户选择的行,因此我保留了一个基本上是 Now() - SeriveDeadline 的字段。 AJAX 更新使其具有倒计时的外观。团队以服务百分比来衡量,因此密切关注剩余时间对他们来说很重要。
    • 是的,这是你不想惹的祸。
    【解决方案3】:

    我做了类似的事情,一旦用户打开票证(行),它就会将该票证分配给该用户并在该记录上设置一个值,例如该特定用户的 FK,所以如果其他人试图打开该票证(行)它会让他们知道它已被分配给其他人。

    【讨论】:

    • 这实际上是我们现在正在做的一部分。我们更改问题的状态代码以表明它正在维护中。我们不断更新一个时间戳,只要它正在更新,它就会将记录保持在此状态。仅此一项仍然会让用户选择他们无法使用的记录。
    【解决方案4】:

    如果可能,限制系统,以便他们将下一个未解决的问题从工作队列中移除,而不是让他们能够从所有未解决的问题中进行选择。

    如果这是不可能的,我想你可以检查一个问题的选择,看看它是否仍然可用。如果它不可用,则在用户单击它后使其消失。这样,您只在他们实际点击某物时才提出请求,而不是不断地轮询数据。

    【讨论】:

    • 很遗憾,由于工作性质,不能选择队列中的下一个。如果它已经被选中,我喜欢当用户点击它时让它消失的想法,但我担心它只会让用户感到沮丧。
    • 我认为用户可能会感到沮丧是一个非常合理的问题。如果你走这条路,你肯定想为用户接受原型。我认为您肯定在并发性与可用性方面处于困境。
    • 感谢您的反馈。你知道,当我第一次开始使用 AJAX 时,我想,“最后,这将使所有用户都能与数据同步工作。”我并不完全失望,但我肯定选择性地忘记了性能是如何考虑的。
    【解决方案5】:

    您是否尝试过增加刷新之间的时间。我希望每 30 秒一次就足够了。 40 个请求/分钟比 1200 个/分钟的负载要少得多。您的用户甚至可能没有注意到差异。

    如果他们这样做,如何在页面上提供一个刷新按钮,以便用户可以在选择项目之前手动刷新列表,以避免他们选择时出现烦人的消息。

    【讨论】:

    • 我开始认为以这种方式使用 AJAX 根本不是一个好的解决方案——无论是每秒还是每 30 秒。刷新是个好主意。我没有想到这一点。网格视图上方的小链接可以很好地工作。尽管如此,它确实失去了一些可用性。
    • 当用户有一段时间没有导航时,我通常使用刷新来通知用户添加了新信息。虽然,我的刷新率更像是 5 分钟。
    • 如果我遗漏了什么,请纠正我,但这似乎是在提倡使用sleep() 调用而不是使用锁来解决并发问题。它不会解决并发编辑的问题,只是掩盖它。
    • @asveikau - 我并不是建议您通过减少更新之间的时间来处理数据库并发问题。我建议减少检查可以使应用程序和数据库在您进行检查时响应更快。您仍然必须处理并发性——即,不要让两个人选择同一个问题,但在选择问题时应该使用事务和时间戳来处理。随着更新频率的降低,两个人可能更有可能选择同一个问题,但至少检查和消息会更快,因为查询更少。
    【解决方案6】:

    我没有看到这个问题,特别是在您提到您已经将工单标记为正在进行/正在维护并且具有该项目的时间戳/版本之后。

    以下内容还不够:

    1. 用户浏览工单并查看可用工单列表,即不包括数据库中正在进行的工单。如果您希望用户也看到正在进行的工单,请在工单状态中明确指出并禁用接受它的选项。
    2. 用户可以通过打开工单来显式或隐式地将工单标记为正在进行中(取决于用户体验/它如何呈现给用户)。
    3. 用户明确将工单移动到不同的状态,即已完成、无效、等待反馈等。

    当在 1 处检索项目时,您会包含时间戳/版本。当 2 发生时,您使用乐观并发方法来确保如果 2 个人尝试同时更新 take the ticket,则只有第一个会成功。

    将会发生的是,对于第二个人来说,update ... where ... timestamp = @timestamp 将找不到任何要更新的记录,您将报告该票已被取走。

    如果您愿意,您可以在上述基础上构建,以便在抢票时更新 UI。这可能是通过在 x 时间后完全刷新当前的票证页面(可能警告/提示用户),或者甚至通过检索为使用 ajax 显示的票证页面更改的票证列表。您仍然拥有前面的步骤,因为此修改只是为了方便用户。

    【讨论】:

    • 你所描述的一切现在正在发生。问题是使用 AJAX 更新 gridview 效率低下。如果我将更新计时器设置为更长的时间间隔,用户就会开始选择相同的记录。乐观并发会检查数据,但会浪费用户的时间。您必须想象一个按优先级排序的包含 300 个项目的列表,最多有 20 个用户选择排名靠前的项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 2014-04-18
    相关资源
    最近更新 更多