【问题标题】:Limiting maximum number of rows in Oracle Database and delete old rows as new ones are inserted限制 Oracle 数据库中的最大行数并在插入新行时删除旧行
【发布时间】:2015-08-26 11:07:24
【问题描述】:

this one 基本相同的问题,但由于它已有 6 年历史,我认为可能值得检查是否有任何添加到 Oracle DB 的功能。

基本上,我们要做的是确保我们在 Oracle DB 中的存档表不会变得太大,因此希望设置要保留的最大行数,并将最旧的行删除为新行被插入。

我找不到比定期清理 cron 作业更简单的方法,但我认为值得询问是否有其他人知道在数据库本身内做这件事的好方法.

编辑以回复 Florin Ghita 的评论:每个事务插入一个行。我们正在考虑将数据库限制为大约 5 或 1000 万行,每天插入大约 700 000 行(因此总共保留大约一周的数据),这使得平均每秒 8 行(尽管峰值次肯定会看到这个数字至少翻倍)。

【问题讨论】:

  • 以什么方式插入行?每笔交易一份,一份声明一份,多份声明,等等?表中有多少行,每秒插入多少行? (仅供参考,Oracle 在过去 6 年中其核心并没有太大变化,所以问题是一样的。并发性迫使您保持 aproximate 行数)
  • 我会查看 DBMS_Scheduler,而不是 cron 作业——将数据库维护代码保存在数据库中。
  • @David Aldridge:谢谢,我也去看看!

标签: database oracle


【解决方案1】:

如果您希望旧记录在新插入时神奇地消失,我认为这并不可行。您可以在插入新记录时编写一个触发器来删除记录,但在对同一表使用查询进行插入时会出现 ORA-04091 错误(例如 insert into mytable (a,b) select 123, max(b)+1 from mytable;

如果你确定这样的冲突永远不会发生,那就继续吧:

create or replace trigger trg_crop_mytable
before insert on mytable for each row
begin
  delete from mytable
  where createdate = (select min(createdate) from mytable)
  and (select count(*) from mytable) = 1000;
end;

不过,我不推荐它,因为我总是担心变异表错误。

然后,您可以结合循环序列使用从 1 到所需最大行数的记录 ID。与其使用 INSERT,不如使用基于此列的 MERGE,从而在重新使用记录 ID 时覆盖旧记录。但是,由于序列中可能存在间隙,您可能不会总是覆盖最旧的记录。

所以是的,有一些可能性(就像以前一样),但最简单和最干净的仍然是你已经拥有的 cron 作业。

【讨论】:

    【解决方案2】:

    感谢您接受我的其他回答。然而,一夜之间我有了另一个想法:据我所知,after 语句触发器不应该导致变异表错误,所以你可能想试试这个:

    create or replace trigger trg_crop_mytable
    after insert on mytable
    begin
      delete from mytable
      where rowid in
      (
        select mytable_rowid
        from
        (  
          select 
            mytable.rowid as mytable_rowid,
            row_number() over (order by createdate desc) as cnt
          from mytable
        )
        where cnt > 1000
      );  
    end;
    

    在插入语句之后触发一次;无论是插入 1 行还是 20,000 行。它为每一行提供一个以 #1 开头的最新行数。然后它会根据需要删除尽可能多的旧行以恢复到表中的 1000 行。

    到目前为止,我看到的唯一问题是性能:每个插入语句都会导致对所有行进行排序和编号,以处理多余的行;对于一张大桌子,这可能需要一些时间。

    【讨论】:

    • 我喜欢这个解决方案,因为它将所有内容都保存在数据库中,而且非常简单,但是在应用它后,我的 Spring 应用程序只会抛出以下异常,没有太多其他解释:org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is weblogic.transaction.RollbackException: setRollbackOnly called on transaction
    • 太糟糕了,它不起作用。更糟糕的是,Java/Spring 对我们隐藏了实际错误。也许 DBA 可以在发生这种情况时查看数据库并解释错误。但是好吧,也许它由于表大小和执行时间长而导致的简单超时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    相关资源
    最近更新 更多