閱讀792 返回首頁    go 阿裏雲 go 技術社區[雲棲]


基於Oracle plsql的多線程編程架構 (附存儲過程)

作者介紹

馮守東北京科訊華通科技發展有限公司高級項目經理。超12年Oracle開發及管理經驗,多年運營商和政府企業級係統運維經驗,曾獲得東軟最佳設計方案獎。熟悉Weblogic、TUXEDO、IBM WAS等相關中間件運維。熟悉MySQL、DB2、Informix等其他開源或商業數據,以及Openstack、Hadoop相關生態係統、網站架構設計等。

 

 引言  

 

1 文檔編製目的

 

在日常編程範圍內有很多大計算量的存儲過程,在業務係統中使用Java實現多線程往往會有參與計算的任務不能均勻分配、不能完全發揮數據庫服務器的高端性能,代碼實現起來門檻較高,比較麻煩。因此,本文檔將通過DIY方式介紹如何在Oracle數據庫服務器實現存儲過程的並行處理。

 

 

2 背景

 

  • 有一個很大的計算過程,參與計算的對象非常多。例如數據固化、應收核定等。

  • 要用PL/SQL逐行處理,當然這這樣做會有大量的讀取和DML操作。

  • 我們使用一台多CPU的數據庫服務器,並且有大量磁盤空間。

  • 我們發現操作係統/SQL並不是非常容易擴展的,它隻使用了1個CPU,並沒有利用整個機器。

  • 由於我們使用固有的單線程程序來處理數據,ORACLE並行查詢不可用!

  • “一個人的活多個人做”並行處理,將固有的任務/數據分解成N個不重疊的組,同時開始PL/SQL子程序N個拷貝。

 

3 範圍

 

本文檔適用於所有使用Oracle 10g的項目,係統吞吐量大,有一定執行時間限製的應用場合。

 

4 詞匯表

 

詞匯名稱

詞匯含義

備注

DBMS_SCHEDULER

Oracle任務調度器

隻有Oracle 10g支持新特性

READ LOCK

Oracle行排他鎖

Oracle 任何版本

Autonomous Transactions

Oracle自治事務

Oracle 任何版本

Dynamic SQL

Oracle 動態SQL

Oracle 任何版本

 

 

總體架構設計

  

 

1 

設計原則和方法

 

原則:

 

  1. 提供一個脫離業務、通用性強的功能組件。

  2. 易於複用,代碼修改少,可配置滿足不同要求。

  3. 對控製重複執行有所考慮。

  4. 組件提供人性化的客戶交互界麵,解決進度情況展示的問題。

  5. 能有一個實現和效率之間的平衡。

 

方法:

 

此組件中的並行執行遵循了幾乎相同的邏輯。通常可以將某個大“任務”劃分為較小的部分,並且並發地執行各個部分。例如,如果需要計算一大批結果並把數據保存到數據庫中,那麼完全可以建立4 個或更多並行會話(P001~P004)來一起執行存儲過程,任務的分派有一個任務分派器來做,分派器可以按照每個進程的負載情況均勻的分派任務。每個會話分別調用預定義的業務過程來執行分派器分派的任務。當需要提交處理結果的時候,可以在每個業務過程內進行保存。

 

此組件作為一種實現架構,可以使一些要求吞吐量大、執行效率高的的操作得到大幅改善,使其能夠呈數量級提高。由於此架構對係統資源要求較高,通常情況下應該在非高峰期而且有足夠資源的情況下之用。

 

2 係統整體架構

 

20170103074933450.png

 

3 係統級組件

 

DBMS_SCHEDULER是Oracle 10G中新增的一個包,與老版本的DBMS_JOB包相比,DBMS_SCHEDULER有很多新特性。Oracle 10g引入DBMS_SCHEDULER來替代先前的DBMS_JOB,在功能方麵,它比DBMS_JOB提供了更強大的功能和更靈活的機製。

 

DBMS_JOB這個程序包存在的問題是它隻能夠處理 PL/SQL 代碼段,即僅能處理匿名程序塊和存儲程序單元。它不能在數據庫外部處理操作係統命令文件或可執行文件中的任何東西。 

 

為此,您將不得不求助於操作係統調度實用工具。另外DBMS_JOB所生成任務進程一旦生成就在數據庫中一直有效,不能在任務結束後自動終止。

 

DBMS_SCHEDULE是直接在數據庫內部的一個作業調度實用程序,強大到足夠處理所有類型的作業,而不隻是 PL/SQL 代碼段。它可以在處理任務執行結束後自動終止。最好的一點是它是數據庫自帶的,無需任何額外的成本,這樣我們在實現上直接使用即可。

 

4 流程圖各部分說明

 

  • 前台用戶:主要是進行程序調度,主要是任務是把我程序執行時機。

 

  • 任務列表:通過一個普通表實現,該表中主要包括了業務過程執行過程中所需要的入參,參數的形式為‘|’分隔的字符串。同時附加了異常及進度信息。該表是由程序開發人員根據具體的業務定義結構並生成入參數據。

 

  • 進程控製:根據係統參數或業務參數調用DBMS_SCHEDULER生成對應個數的服務進程。依據當前進程執行情況,控製任務的重複執行。當出現緊急情況時終止所有服務進程。

 

  • 任務讀取:通過ORACLE的自製事務及鎖特性,實現任務讀取的一致性,即每次服務進程處理一行任務數據的時候,不被其它的服務進程重複讀取。

 

  • 業務過程:該部分同樣由程序開發人員根據具體業務類型開發存儲過程。該過程根據傳入的過程名稱和參數個數動態調用業務存儲過程。

 

  • 服務進程:ORACLE自動管理的進程,服務進程的數量取決於“進程控製”創建的進程數。服務進程主要工作1、通過“任務讀取”獲得“業務過程”的入參。2、調用“業務過程”生成業務數據。

 

  • 數據存儲:業務過程處理之後生成的結果。

 

  • 進程監視:“前台用戶”調用之後任務執行的監控,包括正在執行情況及最終執行結果。

 

 係統接口設計  

 

1 程序開發接口設計

 

此組件向開發人員公布3個係統接口,1個調試接口。

 

 

  • PKG_多線程服務.PRC_進程控製

 

入參:

PRM_PROGRAM   即要調用的業務過程名稱。

PRM_PARMCOUNT 即對應業務過程的參數個數

 

  • PKG_多線程服務.PRC_進程停止

 

直接終止後台正在運行的多線程服務。

 

  • PKG_多線程服務.PRC_調試使用

 

入參:

PRM_PROGRAM   即要調用的業務過程名稱。

PRM_PARMS      即對應業務過程的參數字符串。

 

因為是動態調用存儲過程,所以SC01中的參數個數必須同業務過程個數嚴格對應,提供此方法主要是讓開發人員調試使用。

 

  • 任務列表SC01

 

開發人員要壓入的任務,即業務過程的參數。參數必須以‘|’分隔,並且保證在多線程服務運行的過程中,其他模塊不能對SC01進行DML操作,為實現其他模塊不能操作SC01,在任何DML操作之前必須執行一個語句如下:

 

SELECTCOUNT(*)

      INTO N_EXISTS

      FROM USER_SCHEDULER_JOBSS

     WHERE S.STATE = 'RUNNING'

AND S.JOB_ACTION = 'PKG_多線程服務.PRC_服務進程';

 

綜上所述執行一個ORACLE多線程服務,開發人員隻需要做一項工作即壓入正確SC01參數,然後直接調用即可。

 

2 用戶展示接口設計

 

前台查詢SC02、SC03視圖

 

 數據庫結構設計  

 

1 數據表設計

 

描述:模塊任務分派表Sc01

 

20170103074952198.png

 

2 視圖設計

 

 

  • 描述:運行監視試圖Sc02

 

CREATE OR REPLACE VIEW SC02 AS

SELECT S.JOB_CREATOR        現場創建用戶,

      S.JOB_NAME            線程名稱,

      S.JOB_ACTION          過程名稱,

      S.last_start_date           啟動時間,

      S.COMMENTS           備注,

      (SELECT COUNT(*)

         FROM SC01

        WHERE THREAD_NAME = lower(S.JOB_NAME)

          AND STATUS = '0') 未處理數,

      (SELECT COUNT(*)

         FROM SC01

        WHERE THREAD_NAME = lower(S.JOB_NAME)

          AND STATUS = '1') 運行成功數,

      (SELECT COUNT(*)

         FROM SC01

        WHERE THREAD_NAME = lower(S.JOB_NAME)

          AND STATUS = '-1') 運行失敗數

 FROM USER_SCHEDULER_JOBS S

 ORDERBY S.JOB_NAME;

  

  • 描述:運行結果監視試圖sc03

 

CREATE OR REPLACE VIEW SC03 AS

SELECT S.OWNER             用戶名,

      S.JOB_NAME          線程名稱,

      S.STATUS            線程狀態,

      S.LOG_DATE          日誌時間,

      S.ACTUAL_START_DATE 線程實際運行時間,

      S.RUN_DURATION      線程持續運行時間,

      S.SESSION_ID        會話ID,

      S.SLAVE_PID         進程ID,

      S.ADDITIONAL_INFO   線程備注信息,

      (SELECT COUNT(*) FROM Sc01 WHERE thread_name = lower(S.JOB_NAME) ANDstatus = '0') 未處理數,

      (SELECT COUNT(*) FROM Sc01 WHERE thread_name = lower(S.JOB_NAME) ANDstatus = '1') 運行成功數,

      (SELECT COUNT(*) FROM Sc01 WHERE thread_name = lower(S.JOB_NAME) ANDstatus = '-1')運行失敗數

 FROM USER_SCHEDULER_JOB_RUN_DETAILS S

 ORDER BY S.JOB_NAME;

 

3 數據安全性

 

所需要係統的權限如下:

grant manage scheduler to AHSIMIS;

grant create any job to AHSIMIS;

 

 尚需解決的問題  

 

如果是RAC環境,程序尚不能跨實例運行。

原文發布時間為:2017-01-03

本文來自雲棲社區合作夥伴DBAplus

最後更新:2017-05-13 08:43:23

  上一篇:go  騰訊互娛架構師談遊戲服務器緩存係統怎麼造
  下一篇:go  Greenplum 最佳實踐 - 什麼時候選擇bitmap索引