代码之家  ›  专栏  ›  技术社区  ›  HyderA

如何管理对表单的并发访问?

  •  13
  • HyderA  · 技术社区  · 15 年前

    我们的web应用程序中有一组表单,由多个工作人员管理。这些表格对所有工作人员都是通用的。现在,我们已经实现了一个锁定机制。但问题是,没有可靠的方法可以知道用户何时从系统中注销,因此表单需要解锁。我想知道是否有更好的方法来管理编辑相同数据的并发用户。

    8 回复  |  直到 15 年前
        1
  •  13
  •   Spence    15 年前

    您可以使用乐观并发,这是.Net数据库的设计方式。实际上,您假设通常没有人会同时编辑一行。当这种情况发生时,您可以扔掉所做的更改,或者在两个用户编辑同一行时尝试创建更好的重试逻辑。

    如果您保留了一份开始编辑时所在行的内容,然后将更新写入:

    Update Table set column = changedvalue 
    where column1 = column1prev 
    AND column2 = column2prev...
    

    如果这更新了零行,那么您知道该行在编辑过程中发生了更改,然后您可以处理它,或者简单地抛出一个错误并告诉用户再试一次。

        2
  •  5
  •   Kevin Lacquement    15 年前

    如果第二次更改与第一次不同,则记录现在发生冲突。用户将看到一个新表单,该表单指示哪些字段已被冲突的更新更改。然后,用户有责任解决冲突(通过更新两组更改),或者允许现有的更新继续。

        3
  •  4
  •   Community Mohan Dere    6 年前

    正如Spence所建议的,您需要的是乐观并发性。一个不考虑数据是否改变的标准网站使用我所说的“最后一次写入获胜”。简单地说,无论最后保存到数据库的是哪个连接,该版本的数据都是固定的。在乐观并发中,您使用“first write wins”逻辑,这样如果两个连接试图同时保存同一行,那么提交wins的第一个连接和第二个连接将被拒绝。

    这个机制有两个部分:

    1. 系统或用户如何处理被拒绝的提交。

    确定是否拒绝提交

    两种方法:

    1. 每次提交时更改的比较列
    2. 将数据与其在数据库中提交的版本进行比较。

    rowversion 数据类型,保证在行每次更改时都会更改。好的一面是,它使您可以很容易地滚动自己的逻辑,以确定是否有什么改变。当你得到数据的时候,你就把 行版本 列的值,并在提交时将该值与数据库中当前的值进行比较。如果它们不同,则说明数据自上次检索以来已发生更改,应拒绝提交,否则继续保存数据。

    第二种方法需要将拉取的列与其数据库中现有的提交值进行比较。正如Spence所建议的,如果您尝试更新,但是没有更新任何行,那么很明显其中一个条件失败了。当某些值为null时,此逻辑可能会变得棘手。许多对象关系映射器甚至.NET的DataTable和DataAdapter技术都可以帮助您处理这个问题。

    处理拒绝的提交

    一种更复杂(也更复杂)的方法是向用户显示已更改的内容,允许他们选择要尝试重新提交的项目,在后台您将再次检索数据,用其条目覆盖用户选择的值,然后再次尝试提交。在大容量系统中,这仍然是一个问题,因为当用户尝试重新提交时,数据可能已经再次更改。


    签出概念实际上是用户“锁定”行的悲观并发。正如您所发现的,在无状态环境中很难实现。用户只需在签出某个内容时关闭浏览器,或使用“后退”按钮返回已签出的集并尝试重新提交,这是臭名昭著的。在我看来,在一个基于web的解决方案中尝试走这条路比值得的麻烦多了。假设您写入最后一次更改给定行的用户名,并且具有乐观的并发性,则可以通知拒绝更改的用户之前保存数据的用户。

        4
  •  1
  •   Boerema    15 年前

        5
  •  0
  •   Victor Sorokin    15 年前

    为什么需要查找会话超时?只需同步访问您的数据(表单或其他什么),就可以了。
    更新: 如果您的意思是您有一个“长事务”,其中表单在用户打开编辑器(或其他什么)时被锁定,并且在用户提交更改之前保持锁定,那么:

    • 乐观锁定可能会导致丢失工作,如果用户离开很长时间,然后尝试提交他的更改,发现其他人已经更新了表单。在这种情况下,您可能希望实现表单的显式“锁定”,即用户一开始处理表单就“锁定”表单。其他用户会注意到表单被“锁定”,或者与锁所有者通信以解决问题,或者他可以为自己“重新锁定”表单,从而丢失进程中第一个用户的所有更新。
        6
  •  0
  •   Shane    15 年前

    我们引入了一个非常简单的乐观锁定方案,其工作原理如下:

    • 它的领域
    • 创建窗体时
    • 当表单发布到服务器时 检查中的上次更新日期 数据库中的日期
    • 那么就没有其他人改变世界了 自窗体创建以来的记录 系统更新数据。
    • 如果他们不匹配,那么其他人就有了 创建。系统将用户发送回表单编辑页面,并告诉用户其他人编辑了记录,他们必须重新应用更改。

        7
  •  0
  •   Community Mohan Dere    9 年前

    您可以在表中使用“timestamp”列。参考: What is the mysterious 'timestamp' datatype in Sybase?

    如果是这样,当用户打开一个屏幕时,你必须得到最后一个“ 时间戳 “列到客户端。

    在更新之前更改数据之后,您应该检查“timestamp”列(yours和db),以确定是否有人在编辑时更改了数据。

    如果它改变了,你会提醒一个错误,他必须重新开始。如果不是,则更新数据。时间戳列自动更新。

        8
  •  0
  •   Cory House    15 年前

    最简单的方法是格式化update语句,以包含记录上次更新的日期时间。例如:

    UPDATE my_table SET my_column = new_val WHERE last_updated = <datetime when record was pulled from the db>
    

    这样,只有在上次读取后没有其他人更改记录时,更新才会成功。