微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在SAP HANA中建立只读一次实施?

如何解决如何在SAP HANA中建立只读一次实施?

上下文:我是MSsql的长期开发人员...我想知道如何从SAP HANA实现一次只读选择。

高级伪代码

  1. 通过db proc(查询)收集请求
  2. 通过请求调用API
  3. 存储请求(响应)的结果

我有一个表(A),它是流程输入的来源。流程完成后,它将结果写入另一个表(B)。

如果我只是在表A中添加一列,以避免并发处理器从A中选择相同的记录,这一切都解决了吗?

我想知道如何在不将列添加到源表A的情况下执行此操作。

我尝试过的是在表A和表B之间进行左外部联接,以从表A中获得行(但在表B中没有对应行)。这行不通,或者我没有实现对行进行处理任何处理器只能处理1次。

我有一个存储的proc来处理批量选择:

/*
 *      getBatch.sql
 *
 *      SYnopSIS:  Retrieve the next set of criteria to be used in a search
 *                 request.  Use left outer join between input source table
 *                 and results table to determine the next set of inputs,and
 *                 provide support so that concurrent processes may call this
 *                 proc and get their inputs exclusively.
 */
alter procedure "ACOX"."getBatch" (
     in in_limit int,in in_run_group_id varchar(36),out ot_result table (
         id bigint,runGroupId varchar(36),sourceTableRefId integer,name nvarchar(22),location nvarchar(13),regionCode nvarchar(3),countryCode nvarchar(3)
    )
) language sqlscript sql security definer as
begin       

    -- insert new records:
    insert into "ACOX"."search_result_v4" (
         "RUN_GROUP_ID","BEGIN_DATE_TS","SOURCE_TABLE","SOURCE_TABLE_REFID"   
    )
    select
         in_run_group_id as "RUN_GROUP_ID",CURRENT_TIMESTAMP as "BEGIN_DATE_TS",'acox.searchCriteria' as "SOURCE_TABLE",fp.descriptor_id as "SOURCE_TABLE_REFID"
    from 
        acox.searchCriteria fp
    left join "ACOX"."us_state_codes" st
        on trim(fp.region) = trim(st.usps)
    left outer join "ACOX"."search_result_v4" r
        on fp.descriptor_id = r.source_table_refid
    where
        st.usps is not null
        and r.BEGIN_DATE_TS is null
    limit :in_limit;
    
    -- select records inserted for return:
    ot_result =
    select
         r.ID id,r.RUN_GROUP_ID runGroupId,fp.descriptor_id sourceTableRefId,fp.merch_name name,fp.Location location,st.usps regionCode,'USA' countryCode
    from 
        acox.searchCriteria fp
    left join "ACOX"."us_state_codes" st
        on trim(fp.region) = trim(st.usps)
    inner join "ACOX"."search_result_v4" r
        on fp.descriptor_id = r.source_table_refid
        and r.COMPLETE_DATE_TS is null
        and r.RUN_GROUP_ID = in_run_group_id
    where
        st.usps is not null
    limit :in_limit;

end;

当运行7个并发处理器时,出现35%的重叠。也就是说,在5,000个输入行中,所得行数为6,755。运行时间约为7分钟。

当前,我的解决方包括在源表中添加一列。我想避免这种情况,但它似乎使实现起来更简单。我将在短期内更新代码,但在插入之前包含一条更新语句。

有用的参考文献

解决方法

首先,在任何RDBMS(包括MS SQL)中都没有“只读-一次”。 从字面上看,这意味着给定的记录只能读取一次,然后对于所有后续读取都将“消失”。 (实际上就是队列的工作,或者队列的众所周知的特殊情况:管道)

我认为那不是您想要的。

相反,我相信您希望实现类似于“仅一次”,也就是“仅一次”消息传递的处理语义。尽管这是impossible在潜在分区的网络中要实现的目标,但在数据库的事务上下文中还是有可能的。

这是常见的要求,例如使用批处理数据加载作业,该作业应仅加载到目前为止尚未加载的数据(即在上一个批量加载作业开始后创建的 new 数据)。

很抱歉,很长的篇幅,但是对此的任何解决方案都取决于明确要实际实现的目标。我现在将解决这个问题。

主要的RDBMS很早就发现,如果目标是实现高事务吞吐量,那么阻塞读取器通常是一个糟糕的主意。因此,HANA不会阻止读取器-永远不会(好的,不是永远,但在正常操作设置中)。 “仅一次”处理要求的主要问题实际上不是读取记录,而是处理一次以上或根本不进行的可能性。

可以通过以下方法解决这两个潜在问题:

  1. SELECT ... FOR UPDATE ...应该处理的记录(例如,基于未处理的记录,最多N条记录,奇偶ID,邮政编码等)。这样,当前会话将具有UPDATE TRANSACTION上下文和所选记录上的排他锁。其他事务仍然可以读取这些记录,但是没有其他事务可以锁定这些记录-既不是UPDATEDELETE也不是SELECT ... FOR UPDATE ...

  2. 现在您要进行处理-无论涉及什么:合并,插入,更新其他表,编写日志条目...

  3. 作为处理的最后一步,您想将记录“标记”为已处理。究竟如何实现,这并不重要。 一个可以在表中创建一个 processed 列,并在处理记录后将其设置为TRUE。或者可以有一个单独的表,其中包含已处理记录的主键(也许还有一个 load-job-id 来跟踪多个加载作业)。 无论采用哪种实施方式,都是需要捕获此processed状态的时间点。

  4. COMMITROLLBACK(以防万一出现问题)。这将COMMIT写入目标表的记录,已处理状态信息,,并将释放源表中的排他锁。

如您所见,第1步解决了可能会丢失的记录的问题,方法是选择所有可以处理的通缉记录(即它们没有被其他任何进程独占锁定)。 步骤3 通过跟踪已处理的记录来解决可能多次处理的记录问题。显然,必须在步骤1 中检查此跟踪-这两个步骤是相互关联的,这就是为什么我明确指出它们的原因。最终,所有处理都在同一个DB事务上下文中进行,从而保证了整个事务中的COMMITROLLBACK。这意味着,在提交记录处理后,不会丢失任何“记录标记”。

现在,为什么这种方法比使记录“不可读”更可取? 由于系统中的其他进程。

也许交易记录系统仍在读取源记录,但从未更新过。此事务处理系统不必等待数据加载完成。

或者,也许有人想对源数据进行一些分析,还需要读取这些记录。

或者也许您想并行化数据加载:可以很容易地跳过锁定的记录,而仅对当前“可用于更新”的记录进行处理。参见例如为此Load balancing SQL reads while batch-processing?

好吧,我想您希望有一种更容易食用的东西。 las,据我所知,这就是我对这种要求的处理方式。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。