表插入數據提交後,如何實時通知外部程序?三種主流實現路徑對比:
DECLARE
my_except EXCEPTION;
inserted_cnt1 NUMBER;
inserted_cnt2 NUMBER;
BEGIN
INSERT INTO target_table VALUES (...);
inserted_cnt1 := SQL%ROWCOUNT;
-- 判斷 inserted_cnt1 > 0 確認插入成功
COMMIT;
inserted_cnt2 := SQL%ROWCOUNT; -- 此處為 0
-- 實際上只有提交成功才會執行到此
your_external_process(your_params); -- 調用外部通信過程
EXCEPTION
WHEN OTHERS THEN
-- 根據 SQLCODE 判斷失敗原因
your_fail_handler(your_params);
END;
優點:邏輯集中、事務邊界清晰;缺點:外部調用阻塞主事務、異常處理複雜。
CREATE OR REPLACE TRIGGER trg_notify
AFTER INSERT ON target_table
FOR EACH ROW
BEGIN
your_external_process(:NEW.id, :NEW.data);
END;
關鍵限制:觸發器在提交前觸發,若事務回滾,外部已被誤通知。
改進:引入狀態表/標誌位,觸發器寫入待通知記錄,外部輪詢狀態表確認 COMMITTED 狀態後處理。
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Notifier" AS
public class Notifier {
public static void notifyExternal(String tableName, String pkValue) {
// 實現:HTTP 調用、JMS 發送、Socket 通信、文件寫入等
System.out.println("Notify: " + tableName + " " + pkValue);
}
};
CREATE OR REPLACE PROCEDURE notify_ext (p_table VARCHAR2, p_pk VARCHAR2)
AS LANGUAGE JAVA
NAME 'Notifier.notifyExternal(java.lang.String, java.lang.String)';
CREATE OR REPLACE TRIGGER trg_async_notify
AFTER INSERT ON business_table
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION; -- 關鍵:獨立事務,不受主事務回滾影響
BEGIN
notify_ext('BUSINESS_TABLE', :NEW.id);
COMMIT; -- 自治事務提交
END;
| 技術 | 作用 | 注意事項 |
|---|---|---|
| Java Stored Procedure | JVM 內運行、高性能、豐富生態庫 | 需啟用 JServer、授予 JAVASYSPRIV、SOCKET 權限 |
| AUTONOMOUS_TRANSACTION | 觸發器中實現提交後通知語義 | 自治事務不見主事務未提交變更,需主事務提交後才能查到數據 |
| DBMS_PIPE / AQ / UTL_HTTP | 純 PL/SQL 異步通信替代方案 | 無需 Java、輕量級、受限於 PL/SQL 生態 |
DBMS_JAVA.GRANT_PERMISSION,最小化攻擊面;從同步阻塞到異步解耦,從純 PL/SQL 到 JVM 融合,Oracle 提供了完整的事件驅動架構工具箱。選擇適合業務 SLA 的組合,構建實時、可靠、可觀測的數據變更通知系統。