为了提高性能,SAP ERP提供了多种编号范围缓冲机制,常用的有两种,主内存缓冲和并行缓冲,他们的特征分别如下:
**主内存缓冲(Main Memory Buffering)**
工作原理:
主内存缓冲将编号范围缓存在每个应用服务器的内存中。
当需要新的编号时,系统从内存中获取,而不是每次都访问数据库。
优点:
提高了性能,因为减少了对数据库的访问频率。
对于高频率的编号请求,响应速度更快。
缺点:
无法保证编号的连续性和无间隙性,因为在系统崩溃或重启时,内存中的编号可能会丢失。
在多服务器环境中,不同服务器之间的编号分配可能不一致,导致编号顺序混乱。
** 并行缓冲(Parallel Buffering) **
工作原理:
并行缓冲使用一个透明表(NRIVSHADOW)来管理编号范围。
每个应用服务器和工作进程都有自己的缓冲区,从缓冲表中获取编号。
在回滚的情况下,编号会重新回到缓冲表中,可以在下次请求时再次使用。
优点:
解决了本地缓冲在并行批处理中的问题,提供了更好的并行处理能力。
编号分配尽可能接近未缓冲的行为,基本上是按时间顺序递增的。
在回滚的情况下,编号不会丢失,而是重新回到缓冲表中,确保编号的连续性和无间隙性。
缺点:
实现相对复杂,需要额外的表来管理编号。
在极少数情况下,编号顺序可能会因为回滚而暂时不按时间顺序递增。
**总结**
主内存缓冲适用于对性能要求较高且不严格要求编号连续性的场景,但在多服务器环境中可能会导致编号顺序混乱。
并行缓冲适用于需要高并发处理且要求编号尽可能连续和按时间顺序递增的场景,尽管实现相对复杂,但提供了更好的编号管理和一致性。
工具程序:
如果是主内存缓冲,在做Client
Copy后,或者缓冲条数即将超过设置的条数,就需要重置缓冲,这个工作可以在ST02和SM56来完成,但是这个时候如果有一个工具来查看和重置,会更方便一些。
下面是这个工具的运行界面:
程序去掉了SCREEN和Status,方便移植。代码如下:
*&---------------------------------------------------------------------**& 号码范围缓冲区查看/重置*&---------------------------------------------------------------------**& Baitianzhen*&---------------------------------------------------------------------*REPORT zsnrobuff NO STANDARD PAGE HEADING.
TABLES: noselect.DATA: gt_fldct TYPE lvc_t_fcat, gs_slayt TYPE lvc_s_layo, gt_event TYPE lvc_t_evts, gs_event TYPE lvc_s_evts, gv_repid TYPE sy-repid.DATA: gr_grid TYPE REF TO cl_gui_alv_grid.DATA: BEGIN OF gs_memo. INCLUDE TYPE bnriv2.DATA: iname TYPE msxxlist_v6-name, seled TYPE c, END OF gs_memo.DATA: gt_memo LIKE TABLE OF gs_memo.DATA: BEGIN OF gs_para. INCLUDE TYPE nrivshadow.DATA: seled TYPE c, END OF gs_para.DATA: gt_para LIKE TABLE OF gs_para.DATA: gt_server TYPE TABLE OF msxxlist_v6 WITH HEADER LINE.DATA: gv_rtmsg TYPE bapi_msg.
CLASS lcl_event_receiver DEFINITION DEFERRED .DATA: event_receiver TYPE REF TO lcl_event_receiver.*&---------------------------------------------------------------------**& lcl_event_receiver*&---------------------------------------------------------------------*CLASS lcl_event_receiver DEFINITION. PUBLIC SECTION. METHODS handle_user_command FOR EVENT user_command OF cl_gui_alv_grid IMPORTING e_ucomm. METHODS handle_toolbar FOR EVENT toolbar OF cl_gui_alv_grid IMPORTING e_object e_interactive.ENDCLASS. "lcl_event_receiver9001 DEFINITION
*&---------------------------------------------------------------------**& lcl_event_receiver*&---------------------------------------------------------------------*CLASS lcl_event_receiver IMPLEMENTATION. METHOD handle_user_command. CASE e_ucomm. WHEN 'RESET'. PERFORM reset USING ''. PERFORM refresh. WHEN 'REFRESH'. PERFORM refresh. ENDCASE. ENDMETHOD. "handle_user_command
METHOD handle_toolbar. PERFORM add_button USING e_object : '3' '' '' '', ' ' 'REFRESH' icon_refresh ' 刷新', '3' '' '' '', ' ' 'RESET ' '' '重置'. ENDMETHOD. "handle_toolbarENDCLASS. "lcl_event_receiver9001 IMPLEMENTATION
SELECTION-SCREEN BEGIN OF BLOCK b0 WITH FRAME TITLE btxt0.PARAMETERS: pr_memo RADIOBUTTON GROUP typ USER-COMMAND sele DEFAULT 'X'.PARAMETERS: pr_para RADIOBUTTON GROUP typ.SELECTION-SCREEN END OF BLOCK b0.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE btxt1.SELECT-OPTIONS: s_server FOR gt_server-name NO INTERVALS OBLIGATORY, s_object FOR gs_memo-object.SELECTION-SCREEN END OF BLOCK b1.AT SELECTION-SCREEN OUTPUT. btxt0 = '缓冲类型'. btxt1 = '数据选择'. %_pr_memo_%_app_%-text = '主内存缓冲'. %_pr_para_%_app_%-text = '并行缓冲'. %_s_server_%_app_%-text = '服务器'. %_s_object_%_app_%-text = '编号范围对象'.
INITIALIZATION. CALL FUNCTION 'TH_SERVER_LIST' TABLES list = gt_server EXCEPTIONS no_server_list = 1 OTHERS = 2. LOOP AT gt_server. s_server-sign = 'I'. s_server-option = 'EQ'. s_server-low = gt_server-name. COLLECT s_server. ENDLOOP.
START-OF-SELECTION. PERFORM savelog IN PROGRAM zreplog USING sy-repid '' IF FOUND. PERFORM getdata. PERFORM updatelog IN PROGRAM zreplog IF FOUND. IF pr_memo = 'X'. PERFORM outdata TABLES gt_memo. ELSE. PERFORM outdata TABLES gt_para. ENDIF.
*&---------------------------------------------------------------------**& 获取数据,程序执行和刷新的时候调用*&---------------------------------------------------------------------*FORM getdata. DATA: hitkz.
DATA: lt_data TYPE TABLE OF bnriv2 WITH HEADER LINE. CLEAR: gt_memo,gs_memo,gs_para,gt_para.
CASE 'X'. WHEN pr_memo. LOOP AT s_server. CLEAR lt_data[]. CALL FUNCTION 'SAPTUNE_NUMBUF_CONTENTS' DESTINATION s_server-low TABLES contents = lt_data EXCEPTIONS system_failure = 1 MESSAGE gv_rtmsg communication_failure = 2 MESSAGE gv_rtmsg OTHERS = 4. IF sy-subrc = 0. LOOP AT lt_data WHERE object IN s_object. MOVE-CORRESPONDING lt_data TO gs_memo. gs_memo-iname = s_server-low. APPEND gs_memo TO gt_memo. ENDLOOP. ELSE. MESSAGE i000(oo) WITH '服务器Error:' s_server-low gv_rtmsg. ENDIF. ENDLOOP. WHEN pr_para. SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_para FROM nrivshadow CLIENT SPECIFIED WHERE object IN s_object. LOOP AT gt_para INTO gs_para. CLEAR hitkz. LOOP AT s_server. IF gs_para-instanz CS s_server-low. hitkz = 'X'. EXIT. ENDIF. ENDLOOP. IF hitkz IS INITIAL. DELETE gt_para. CONTINUE. ENDIF. ENDLOOP. ENDCASE.ENDFORM. "getdata*&---------------------------------------------------------------------**& outdata*&---------------------------------------------------------------------*FORM outdata TABLES t_out. gv_repid = sy-repid. gs_slayt-zebra = 'X'. gs_slayt-detailinit = 'X'. gs_slayt-box_fname = 'SELED'.
gs_event-name = slis_ev_caller_exit_at_start. gs_event-form = 'REG_EVENT'. APPEND gs_event TO gt_event.
IF pr_memo = 'X'. PERFORM catset1 TABLES gt_fldct USING: 'INAME ' ' ' ' ' '实例', 'CLIENT ' 'BNRIV2' 'CLIENT ' 'CLIENT', 'OBJECT ' 'BNRIV2' 'OBJECT ' '', 'SUBOBJECT ' 'BNRIV2' 'SUBOBJECT ' '', 'NRRANGENR ' 'BNRIV2' 'NRRANGENR ' '', 'TOYEAR ' 'BNRIV2' 'TOYEAR ' '', 'FROMNUMBER' 'BNRIV2' 'FROMNUMBER' '', 'TONUMBER ' 'BNRIV2' 'TONUMBER ' '', 'NRLEVEL ' 'BNRIV2' 'NRLEVEL ' '', 'EXTERNIND ' 'BNRIV2' 'EXTERNIND ' ''. ELSE. PERFORM catset1 TABLES gt_fldct USING: 'INSTANZ ' 'NRIVSHADOW' 'INSTANZ ' '实例和进程标识', 'CLIENT ' 'NRIVSHADOW' 'CLIENT ' 'CLIENT', 'OBJECT ' 'NRIVSHADOW' 'OBJECT ' '对象名称', 'SUBOBJECT' 'NRIVSHADOW' 'SUBOBJECT' '子对象', 'NRRANGENR' 'NRIVSHADOW' 'NRRANGENR' '序号区间编号', 'TOYEAR ' 'NRIVSHADOW' 'TOYEAR ' '终止年', 'FROMNR ' 'NRIVSHADOW' 'FROMNR ' '缓冲区自', 'TONUMBER ' 'NRIVSHADOW' 'TONUMBER ' '缓冲区至', 'NRLEVEL ' 'NRIVSHADOW' 'NRLEVEL ' '编号范围状态', 'G_FROMNR ' 'NRIVSHADOW' 'G_FROMNR ' '间隔自', 'G_TONR ' 'NRIVSHADOW' 'G_TONR ' '间隔至'. ENDIF....