SAP 應用系統架構
應用層運行着DIALOG進程,每個DIALOG進程綁定一個數據庫進程,DIALOG進程與GUI進行通信,每次GUI向應用服務器發送請求時都會通過dispatcher服務為每個GUI的請求分配一個Dialog進程.一個程序運行時,GUI與Dialog進行需要多次通信,每次通信使用的Dialog進程不一定相同,在Dialog進程將控制權轉給前台的GUI時,由於Dialog進程同數據庫進程綁定,會觸發一個隱式數據庫提交(COMMIT WORK),如果在Dialog進程發生A類型錯誤,則觸發隱式的數據庫回滾(Rollback)
SAP LUW
SAP LUW是DB LUW的一個增強,受體系結構限制,SAP程序每次屏幕切換時(控制權從后台DIALOG進程轉移到前台GUI的Session),都會觸發一個隱式的數據庫提交,一個程序在運行是會產生多個DB 的LUW,這樣無法做到全部提交或全部回滾,在某些業務場景下,這種事務的提交機制不足以保證數據的一致性,為此有有了SAP LUW機制.SAP LUW是一種延遲執行的技術,它將本來需要執行的程序塊,記錄下來.記錄的位置在內存或DB Table中,如perform on commit 會記錄到內存中,update Funciton module即可以記錄到內存也可以記錄到VBMOD 和VBMOD表中.系統在執行COMMIT WORK的時候會查詢記錄,真正執行需要運行的代碼,COMMIT WORK一般在最后一個屏幕執行,這樣就實現了將跨屏幕的數據更新邏輯綁定到一個DB LUW中,實現復雜情況數據更新的一致性
SAP LUW的綁定方式
CALL FUNCTION...IN UPDATE TASK,
該種方式需要Funciton類型為Update Module類型,同時在調用時使用IN UPDATE TASK參數.
在程序調用 Update Module進行更新時分為本地和非本地
非本地方式:
注冊的更新函數記錄在VBMOD 和VBMOD表中,COMMIT WORK 時更新操作在UPDATE進程中執行,此時調用程序不等待被調用函數的返回,使用的為異步方式.如果使用COMMIT WORK AND WAIT,此時調用程序等待被調用函數的返回,使用的為同步方式.
本地方式
在調用函數前需要執行 SET UPDATE TASK LOCAL. 這樣所有在該語句后使用CALL FUNCTION...IN UPDATE TASK注冊的更新函數不會記錄到數據庫中,而是記錄在內存中,在Commit work之后,會從內存取得待執行的函數,在同一個Dialog進程中執行數據的更新,本地方式更新采用的是同步方式,即使在Commit work后指定了and wait參數,仍然是同步執行.
在使用COMMIT WORK之后 SET UPDATE TASK LOCAL的效果會被清除掉,如果COMMIT WORK后注冊的更新函數仍然需要采用本地方式,需要再執行一次 SET UPDATE TASK LOCAL語句.
優缺點對比
本地方式不將待執行的更新函數寫到數據表中,減少了I/O操作,效率上較高,但由於采用的是同步方式,程序需等待更新結果,用戶交互時的會感覺程序運行較慢
非本地方式會將更新結果記錄到數據表中,可以通過SM13查看更新情況,同時由於可以進行異步更新,用戶交互時感覺會比較快
CALL FUNCTION... IN BACKGROUND TASK DESTINATION,
是一種對RFC函數進行事務綁定的方式
PERFORM ... ON COMMIT
將待執行的程序塊注冊到內存中,可以使用LEVEL參數指定優先級,優先級按升序進行排列,較小的會優先執行.
使用ON COMMIT參數注冊的subroutine,如果同樣名字的subroutine被注冊了多次,在COMMIT WORK時只執行一次,IN UPDATE TASK方式執行的Funciton沒有這個限制
綁定方式的執行順序
PERFORM ON COMMIT 會優先執行,如果中斷,CALL FUNCTION... IN BACKGROUND TASK和CALL FUNCTION...IN UPDATE TASK, DESTINATION 將不會執行,可以保證數據的全部提交和全部回滾
建議不要混合使用CALL FUNCTION... IN BACKGROUND TASK和CALL FUNCTION...IN UPDATE TASK,因為一個是針對本地數據進行的更新,一個是遠程數據,從技術上猜測,跨數據庫的提交與回滾很難實現,故同時使用這兩種方式可能會帶來數據不一致的問題,除非本地和遠程數據不需要保持數據的一致
V1 & V2 Update
圖例說明
Immediate start 表示V1方式,更新出錯后,可以在SM13里重新執行
Immediate start -no restrat possible V1方式,出錯后不可以在SM13里重新執行,有些更新脫離具體程序后再執行可能會帶來數據的不一致,可以考慮使用這種方式
Start delayed V2方式 V1方式更新完成后觸發,
Collective run V2方式 需使用Collective(RSM13005)程序手動或JOB方式執行,
更新函數分為V1和V2
V1優先級高於V2,V2被設計為依賴於V1,適合執行需要在V1完成后進行的操作,
V1更新使用V1進程處理,V1進程名字一般為UPD,V1進程綁定獨立的數據庫進程.在V1進程中調度的更新函數如果更新失敗,回滾,不進行V2操作.成功則提交更改到數據庫,同時刪除所有的SAP鎖
V2更新使用V2進程處理,如果沒有配置V2進程則共用V1進程,V2進程名字為UP2,V2更新在獨立DB LUW中,V2更新回滾后不會影響到V1更新提交的數據,由於V1更新結束后會刪除SAP的鎖,所以V2更新是在沒有邏輯鎖的情況下進行的,V2更新出錯后可以在SM13中重新執行
SAP Locks
SAP 的鎖是一種邏輯鎖,通過加鎖函數和解鎖函數進行處理
鎖類型
S 共享鎖 讀鎖,可以累加
E 獨占鎖 寫鎖 進程內可以累加
X 排他鎖 寫鎖 不可以累加
慎用S鎖,S鎖的累加特性會造成鎖無法徹底釋放,造成其他程序無法寫入,E鎖可以保證只加一次鎖
鎖對象
通過鎖對象可以生成加鎖和解鎖函數
其中scope 參數 1 表示程序內,有效 2 表示 update module 內有效 3 全部
_wait 表示如果對象已經被鎖定,是否等待后再嘗試加鎖,最大的等待時間 有系統參數 ENQUE/DELAY_MAX控制
_COLLECT 參數表示是否收集后進行統一提交,COLLECT 是一種緩存與批處理方法,即如果指定了Collect,加鎖信息會放到Lock Container 中,Lock Container實際上是一個funciton Group控制的內存區域,如果程序中加了很多鎖,鎖信息會先放到內存中,這樣可以減少對SAP鎖管理系統訪問,若使Lock Container中的鎖生效,需執行FLUSH_ENQUEUE 這個Funciton,將鎖信息更新到鎖管理系統中,此時加鎖操作生效,使用函數 RESET_ENQUEUE可以清除Lock Container中的鎖信息
釋放鎖
調用DEQUEUE函數
如果程序更新用到到V1 Update時,在commit work是會刪除所有的鎖
程序中止
rollback
為什么需要使用SAP Lock
SAP Lock是一種邏輯鎖,相對於DB Lock,是一種輕量級的鎖,DB Lock一旦發現不能加鎖會進行延遲等待,使用SAP Lock 一定程度上可以減少對DB Lock的占用,避免死鎖,同時合理使用SAP Lock可以保證數據的一致性
其他
select for update 是在DB層次上加的鎖
參考
SM66查看活動進程,如果有V1和V2更新,可以看到UPD和UP2進程
SM13查看出錯或未執行完的V1和V2更新