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

在事务数据库中撤消

  •  3
  • rics  · 技术社区  · 17 年前

    一方面,建议用户有多级(无限)撤销的可能性,如它所述 here Memento Command .

    换言之,撤消到最后一次提交的事务只是回滚的时候,但是怎么可能回到不同的时刻呢?

    更新 (基于到目前为止的答案):我不一定希望在修改已经提交的情况下执行撤消操作,我将关注一个运行中的应用程序,该应用程序具有打开的事务。每当用户单击save就意味着提交,但是在保存之前-在同一事务期间-撤消应该起作用。我知道使用数据库作为持久层只是一个实现细节,用户不应该为此烦恼。如果我们在数据库中使用的是一个“撤销”这个词,那么根本上就是用一个“撤销”这个词来理解的。

    那么,如果在同一个事务中“由于任何更改而产生的级联效应”,如何实现客户机级别的撤消呢?

    5 回复  |  直到 9 年前
        1
  •  6
  •   William    17 年前

    在数据库和GUI中撤销的概念是完全不同的;GUI将是一个单用户应用程序,与其他组件的交互程度很低;数据库是一个多用户应用程序,在这种应用程序中,任何更改都可能产生级联效应。

    要做的是允许用户尝试将以前的状态作为一个新事务应用,这可能有效,也可能不起作用;或者只是在提交后没有撤消(类似于保存后没有撤消,这是许多应用程序中的一个选项)。

        2
  •  4
  •   Tony Andrews    17 年前

    一些(全部?)DBMS支持保存点,允许部分回滚:

    savepoint s1;
    insert into mytable (id) values (1);
    savepoint s2;
    insert into mytable (id) values (2);
    savepoint s3;
    insert into mytable (id) values (3);
    rollback to s2;
    commit;
    

    我不认为在提交之后再尝试撤消是不实际的,因为你给出了*的原因,可能还有其他原因。如果它在某些场景中是必需的,那么您将不得不构建大量代码来完成它,并考虑触发器的影响等。

    • 但我不认为不断增加的序列有什么问题吗?
        3
  •  2
  •   Philippe Grondier    17 年前

    我们在数据库中开发了这样一种可能性,通过跟踪应用于数据的所有事务(并非所有事务,只是那些不到3个月的事务)。基本的想法是能够看到谁在什么时候做了什么。每个由其GUID唯一标识的数据库记录可以被视为一个INSERT、多个UPDATEs语句和最后一个DELETE语句的结果。由于我们跟踪所有这些SQL语句,并且由于INSERT是全局插入(INSERT语句中保留了对所有字段值的跟踪),因此可以:

    • 知道谁修改了哪个字段,何时修改:Paul在形式发票中插入了一行新行,Bill重新确定了项目的单价,Pat修改了最终订购数量,等等)
    • “INSERT”撤消是基于唯一标识符的“DELETE”

      “删除”撤消等同于第一次插入,然后是所有更新

    • 因为我们不知道 超过3个月的交易, 撤消不是总是可用的。

    对这些功能的访问仅限于数据库管理员,因为不允许其他用户在业务规则之外进行任何数据更新(例如:一旦供应商同意了采购订单,那么在采购订单行上“撤消”的含义是什么?)。说实话,我们很少使用这个选项(一年几次?)

        4
  •  2
  •   Kai Huppmann    17 年前

    1. 用户希望撤消他所做的操作,而不管这些操作是否导致没有/一个/多个数据库事务
    2. 用户希望撤消他所做的操作(而不是其他人的操作)

    从我的观点来看,数据库是实现细节,一种工具,你可以作为程序员用来存储数据。回滚是一种可以帮助您这样做的撤消,它不是用户撤消。使用回滚意味着让用户参与他不想知道、不理解(也不必了解)的事情,这绝不是一个好主意。

        5
  •  1
  •   ConcernedOfTunbridgeWells    17 年前

    在以前的数据库中实现任意删除将需要你的逻辑回滚。其工作原理如下:

    删除记录时,将其标记为“已删除”。更改该行时,将创建新行并更新旧行以反映其过时情况。有了版本号,您就可以找到要回滚到的前一个版本号。

    如果您需要引用完整性(即使您认为不需要),并且能够处理额外的I/O,那么您还应该拥有一个父表,其中键作为所有版本中记录的占位符。

    在Oracle上,聚集表对此很有用;父表和版本表都可以位于同一位置,从而将I/O的开销降至最低。在SQL Server上,包含该键的覆盖索引(可能聚集在实体键上)将减少额外的I/O。

    推荐文章