PL/SQL 作業系統呼叫
我正在嘗試直接或間接地從 Oracle Apex 發起系統呼叫。它似乎只接受 PL/SQL 過程,所以我對此進行了迭代:
begin :p3_request_id := sequence.nextval; insert into request (id, user, target, operator) values (:p3_request_id, :p3_user_id, :p3_target_id, :app_user); -- part that doesn't work: host('/home/oracle/scripts/dbq/fork.py ' || :p3_request_id); end;
很遺憾:
ORA-06550: line 9, column 3: PLS-00201: identifier 'HOST' must be declared ORA-06550: line 9, column 3: PL/SQL: Statement ignored
經過進一步研究,我發現要使其正常工作,我必須聲明此過程並執行後台守護程序腳本……這似乎相當複雜和脆弱(還有一個需要擔心、監控等的過程)。還有其他方法可以啟動系統程序嗎?
從技術上講,您可以創建從 APEX 程序呼叫的Java 儲存過程或
dbms_scheduler
外部作業。然而,這樣做幾乎肯定是一個錯誤。首先,您會遇到並發問題。例如,如果您確實從 APEX 程序中呼叫了 Python 腳本,那麼該程序將立即啟動並且不會等待您的事務完成。假設您進行了同步呼叫,當您的腳本執行並訪問數據庫時,您插入到
request
表將不可見,因為您的事務尚未送出。如果您進行了非同步呼叫,則該行可能可見也可能不可見,因為事務可能尚未送出,也可能尚未送出。此外,您的 APEX 程序稍後可能會在某些其他頁面程序中遇到錯誤,這會導致事務回滾,這也會導致腳本無法看到該行。分解事務以便您在呼叫腳本之前送出將確保該行可見,但可能會在您的應用程序中產生許多其他數據一致性和數據質量問題。相反,實現某種排隊機制幾乎總是更有意義。無論您使用 Oracle AQ 還是只寫入
request
表並具有從表中讀取並執行您的 Python 程式碼的單獨作業不如某種隊列的存在重要。這將兩段程式碼解耦——寫入請求的程式碼可以具有適當的事務邊界,而讀取請求的程式碼不必擔心嘗試處理尚未送出或可能已回滾的請求. 這並不復雜和脆弱——這是一種更強大的方法。是的,您可能需要監控正在處理請求的作業(您可能能夠依賴對 Oracle 警報日誌或您已經使用的任何調度工具的日誌的現有監控)。但這通常比嘗試調試某些請求未得到處理或外部腳本始終無法找到行的原因要容易得多。