基于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
 
系统整体架构

 

 

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

 

 

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

相关文章
|
2月前
|
存储 Oracle NoSQL
【赵渝强老师】Oracle的体系架构
Oracle数据库的核心在于其体系架构,主要包括数据库与实例、存储结构、进程结构和内存结构。数据库由物理文件组成,实例则是内存和进程的组合。存储结构分为逻辑和物理两部分,进程结构涉及多个后台进程如SMON、PMON、DBWn等,内存结构则包含SGA和PGA。掌握这些知识有助于更好地管理和优化Oracle数据库。
|
2月前
|
存储 Oracle 关系型数据库
oracle服务器存储过程中调用http
通过配置权限、创建和调用存储过程,您可以在Oracle数据库中使用UTL_HTTP包发起HTTP请求。这使得Oracle存储过程可以与外部HTTP服务进行交互,从而实现更复杂的数据处理和集成。在实际应用中,根据具体需求调整请求类型和错误处理逻辑,以确保系统的稳定性和可靠性。
121 0
|
3月前
|
设计模式 人工智能 算法
编程之旅:从代码到架构的感悟
【9月更文挑战第33天】在编程的世界里,代码不仅是实现功能的工具,更是连接思想与现实的桥梁。本文将通过个人的编程经历,分享从编写第一行代码到设计系统架构的旅程,探索编程背后的哲学和技术演变。我们将一起思考,如何在代码的海洋中找到自己的航向,以及在这个过程中如何不断成长和适应变化。
|
4月前
|
存储 缓存 Java
JAVA并发编程系列(11)线程池底层原理架构剖析
本文详细解析了Java线程池的核心参数及其意义,包括核心线程数量(corePoolSize)、最大线程数量(maximumPoolSize)、线程空闲时间(keepAliveTime)、任务存储队列(workQueue)、线程工厂(threadFactory)及拒绝策略(handler)。此外,还介绍了四种常见的线程池:可缓存线程池(newCachedThreadPool)、定时调度线程池(newScheduledThreadPool)、单线程池(newSingleThreadExecutor)及固定长度线程池(newFixedThreadPool)。
|
5月前
|
设计模式 算法 PHP
深入理解PHP中的数组操作探索编程之美:从代码到架构的思维转变
【8月更文挑战第24天】在PHP编程中,数组是基础且强大的数据结构。本文将通过浅显易懂的方式,介绍如何在PHP中高效地操作数组,包括创建、遍历、排序和过滤等常见任务。无论你是初学者还是有经验的开发者,这篇文章都会带给你新的启示。 【8月更文挑战第24天】在编程的世界中,代码不仅仅是冰冷的字符排列,它承载着思想、解决问题的智慧和创新的灵魂。本文将通过个人的技术感悟,带领读者从编写单一功能的代码片段出发,逐步深入到整个软件架构的设计哲学,探索如何将代码块转化为高效、可维护和可扩展的系统。我们将一起见证,当代码与架构思维相结合时,如何引发技术实践的革命性飞跃。
|
5月前
|
存储 前端开发 数据库
神秘编程世界惊现强大架构!Web2py 的 MVC 究竟隐藏着怎样的神奇魔力?带你探索实际应用之谜!
【8月更文挑战第31天】在现代 Web 开发中,MVC(Model-View-Controller)架构被广泛应用,将应用程序分为模型、视图和控制器三个部分,有助于提高代码的可维护性、可扩展性和可测试性。Web2py 是一个采用 MVC 架构的 Python Web 框架,其中模型处理数据和业务逻辑,视图负责呈现数据给用户,控制器则协调模型和视图之间的交互。
48 0
|
6月前
|
Kubernetes Cloud Native 微服务
探索云原生技术:Kubernetes在微服务架构中的应用Python编程之旅:从基础到进阶
【7月更文挑战第31天】随着云计算技术的迅猛发展,云原生概念应运而生,它代表了一种构建和运行应用程序的全新方式。本文将通过实际代码示例,深入探讨Kubernetes这一云原生关键技术如何在微服务架构中发挥其强大的作用。我们将从容器化开始,逐步过渡到Kubernetes集群的搭建与管理,最后展示如何部署和管理一个微服务应用。
73 2
|
5月前
|
存储 运维 Oracle
常用的几种Oracle架构介绍
常用的几种Oracle架构介绍
79 0
|
5月前
|
程序员
软件设计与架构复杂度问题之战略编程与战术编程的主要区别如何解决
软件设计与架构复杂度问题之战略编程与战术编程的主要区别如何解决
|
6月前
编程之路:从代码到架构的心路历程
【7月更文挑战第9天】在数字世界的迷宫中,每一行代码都承载着创造者的梦想与挑战。本文将通过个人技术感悟的镜头,探索编程实践的深层次价值,从最初的代码编写到复杂的系统架构设计,揭示技术成长的内在逻辑和情感变迁。我们将一同穿梭在技术的森林里,寻找那些让代码生动起来的秘密。
42 2

热门文章

最新文章

推荐镜像

更多