精华内容
下载资源
问答
  • IT知名企业常见面试题实例与详解

    千次阅读 2007-11-09 10:26:00
    IT知名企业常见面试题实例与详解IT名企面试步骤一般为四面:一面:技术面,考核技能水平;二面:综合面:考核综合素质;三面:HR面,职业规划,优势与劣势,期望工资与工作地点;四面:老总面,最后决定命运。95d565...
      
    

    IT知名企业常见面试题实例与详解

    IT名企面试步骤一般为四面:一面:技术面,考核技能水平;二面:综合面:考核综合素质;三面:HR面,职业规划,优势与劣势,期望工资与工作地点;四面:老总面,最后决定命运。95d565ef66©应届生Y

    一、 通用面试例题分析

    1. 在学校里你学习了哪些课程,成绩如何?

    答:首先看看计算机专业的课程:系统原理、微机原理、汇编语言、网络基础、Visual Basic编程、SQLHTML语言、高等数学……基本上以对计算机科学结构性、设计性的课程为主。然后是自动化专业,这张课表上少了汇编语言等系统基础的课程,增加了POWER BUILDERNT Sever等网络方面的内容,毕竟现在的自动化与网络密不可分。而信息管理工程专业的课程就显然偏重应用的色彩。除VBVC编程语言的课程外,WindowsPhotoshopFlash/Firework/Dreamweaver网页制作工具等课程也赫然在目。4b5ce2fe28©应届

    2. 想着手编写一个程序,在整个开发过程中,其中包含了大量细节,并推荐了许多步骤和文档,那么,时刻提醒自己注意的是什么问题?整个过程是什么?

    答:时刻提醒自己注意的问题是:

    (1) 对象是什么?(怎样将自己的项目分割成一系列单独的组件?)

    (2) 它们的接口是什么?(需要将什么消息发给每一个对象?)

    整个过程可划分为四个阶段,阶段0刚刚开始采用某些形式的结构。

    阶段0:拟出一个计划2e2d7fbdea©应届生Yi

    第一步是决定在后面的过程中采取哪些步骤。

    在这个阶段,可能要决定一些必要的附加处理结构。在整个过程中设置几个标志,或者路标,将更有益于你集中注意力。经过了一个接一个的路标以后,可对自己的进度有清晰的把握。

    阶段1:要制作什么?6fe97759aa

    在上一代程序设计中(即过程化或程序化设计),这个阶段称为建立需求分析和系统规格。应尽可能总结出自己系统的一套完整的使用条件或者应用场合

    阶段2:如何构建?

    在这一阶段,必须拿出一套设计方案,并解释其中包含的各类对象在外观上是什么样子,以及相互间是如何沟通的。©应届生求职网

    阶段3:开始创建

    全面的思考、周密的准备、良好的构造不仅使程序更易构建与调试,也使其更易理解和维护,而那正是一套软件赢利的必要条件。

    构建好系统,并令其运行起来后,必须进行实际检验,以前做的那些需求分析和系统规格便可派上用场了。全面地考察自己的程序,确定提出的所有要求均已满足。现在一切似乎都该结束了?5568161

    阶段4:校订

    第一次做的东西并不完善,所以需为自己留下一个深入学习、认知的空间,再回过头去作一些改变。对于要解决的问题,随着对它的学习和了解愈加深入,可能需要做出大量改动。进行这些工作的一个动力是随着不断的改革优化,终于能够从自己的努力中得到回报,无论这需要经历一个较短还是较长的时期,达到理想的状态。

    3. 什么是UML8e8850243b©应届生YingJieSheng.COM©8aa0d594fc

    答:是一种能够描述问题、描述解决方案、起沟通作用的语言。这就是UML

    UML(Unified Modeling Language 统一建模语言)是由Rational公司发明,目前由OMG(标准化对象管理机构)维护。作为一种建模语言,UML的定义包括UML语义和UML表示法两个部分:

    UML语义da13©应届ngJieSheng.COM©60d149af 1f

    描述基于UML的精确元模型定义。元模型为UML的所有元素在语法和语义上提供了简单、一致、通用的定义性说明,使开发者能在语义上取得一致,消除了因人而异的最佳表达方法所造成的影响。此外UML还支持对元模型的扩展定义。

    UML表示法

    定义UML符号的表示法,为开发者或开发工具使用这些图形符号和文本语法为系统建模提供了标准。这些图形符号和文字所表达的是应用级的模型,在语义上它是UML元模型的实例。标准建模语言UML的重要内容可以由下列五类图(9种图形)来定义:用例图、静态图、行为图、交互图、实现图。

    从应用的角度看,当采用面向对象技术设计系统时,首先是描述需求;其次根据需求建立系统的静态模型,以构造系统的结构;第三步是描述系统的行为。其中在第一步与第二步中所建立的模型都是静态的,包括用例图、类图(包含包)、对象图、组件图和配置图等五个图形,是标准建模语言UML的静态建模机制。其中第三步中所建立的模型或者可以执行,或者表示执行时的时序状态或交互关系。它包括状态图、活动图、顺序图和合作图等四个图形,是标准建模语言UML的动态建模机制。因此,标准建模语言UML的主要内容也可以归纳为静态建模机制和动态建模机制两大类。

    4. 什么是软件重用?

    答:软件重用(Reuse)是软件工程中最重要的思想之一,只有软件重用,才能降低软件成本,提高软件的质量。你在对一个软件进行分析的时候,找出可以重用的对象,有助于你开发高效的软件系统。正如前面所说的,你不必把软件分析的过分细致,你只需从中找出关键性的、能够重用的对象就足够了。剩下的事情,就是对这些对象分配属性和方法,并充分的使用这些对象就好了。

    81) 编写项目视图和范围文档

    系统的需求包括四个不同的层次:业务需求、用户需求和功能需求、非功能性需求。

    2) 用户群分类cdcd5072bb©应届生ingJieSheng.COM©036ebd0562

    用户分成不同的用户类。与UMLUsecaseActor概念一样,用户类不一定都指人,也可以包括其他应用系统、接口或者硬件,这样做使得与系统边界外的接口也成为系统需求。

    3) 选择用户代表

    4) 建立核心队伍ea2e©应届

    5) 确定使用实例

    6) 召开联合会议

    7) 分析用户工作流程©应届生

    8) 确定质量属性

    9) 检查问题报告

    10) 需求重用027327d8©应届gJieSheng.COM©e85d8ecacd

    5. 谈谈CMMI的起源

    答:随着人们对CMM研究的不断深入,其他学科也结合本系统的特点,陆续推出了自己的CMM模型。例如,人力资源能力成熟度模型、系统工程能力成熟度模型等等:

    1 SW-CMM (Software CMM) 软件CMM7260ae62e3©应届生

    2 SE-CMM (System Engineering CMM) 系统工程CMM

    3 SA-CMM (Software Acquisition CMM) 软件采购CMM

    4 IPT-CMM (Integrated Product Team CMM) 集成产品群组CMMb794217348©

    5 P-CMM (People CMM) 人力资源能力成熟度模型

    为了以示区别,国内外很多资料把CMM叫做SW-CMM

    6. ERP是个什么概念?778dfaecdc©应届生

    答:本世纪90年代初,美国著名的IT分析公司Gartner Group Inc根据当时计算机信息处理技术ITInformation Technology)的发展和企业对供应链管理的需要,对信息时代以后制造业管理信息系统的发展趋势和即将发生的变革作了预测,提出了企业资源计划ERPEnterprise Resources Planning)这个概念。

    7. ERP系统与MRP-的区别是什么?

    答:ERP是在MRP-基础上进一步发展起来的企业管理信息系统,为了进一步理解ERP系统的概念及其主要功能,需要弄清ERPMRP-之间的区别。 e76fc

    51) 在资源管理范围方面的差别

    MRP-主要侧重对企业内部人、财、物等资源的管理,ERP系统提出了供应链(Supply Chain)的概念,即把客户需求和企业内部的制造活动以及供应商的制造资源整合在一起,并对供应链上的所有环节进行有效管理,这些五一节包括订单、采购、库存、计划、生产制造、质量控制、运输、分销、服务与维护、财务管理、人事管理、实验室管理、项目管理、配方管理等。

    2) 在生产方式管理方面的差别 754b

    MRP-系统把企业归类为几种典型的生产方式来进行管理,如重复制造、批量生产、按订单生产、按订单装配、按库存生产等,针对每一种类型都有一套管理标准。而在80年代末、90年代初期,企业为了紧跟市场的变化,多品种、小批量生产以及看板式生产成为企业主要采用的生产方式,而ERP则能很好地支持和管理这种混合型制造环境,满足了企业多元化经营需求。

    3) 在管理功能方面的差别

    ERP除了MRP-系统的制造、分销、财务管理功能外,还增加了支持整各个环节之间的运输管理和仓库管理;支持生产保障体系的质量管理、实验室管理、设备维修和备品备件管理;支持对工作流(业务处理流程)的管理。 a1264b2©应届

    4) 在事务处理控制方面的差别

    MRP-是通过计划的及时滚动来控制整个生产过程,它的实时性较差,一般只有实现事中控制。而ERP系统支持在线分析处理OLAPOnline Analytical Processing)、售后服务及质量反馈,强调企业的事前控制能力,它可以将设计、制造、销售、运输等通过集成来并行地进行各种相关的作业,为企业提供了对质量、适应变化、客户满意、效绩等关键问题的实时分析能力。

    此外,在MRP-中,财务系统只是一个信息的归结者,它的功能是将供、产、销中的数量信息转变为价值信息,是物流的价值反映。而ERP系统则将财务计划功能和价值控制功能集成到整个供应链上,如在生产计划系统中,除了保留原有的主生产计划、物料需求计划和能力计划外还扩展了销售执行计划SOP和利润计划。6e7929b125©应届生ng

    5) 在跨国(或地区)经营事务处理方面的差别

    现代企业的发展,使得企业内部各个组织单元之间、企业与外部的业务单元之间的协调变得越来越多和越来越重要,ERP系统运用完善的组织架构,从而可以支持跨国经营的多国家地区、多工厂、多语种、多币制应用需求。

    6) 在计算机信息处理技术方面的差别cbf4caaed3©应届

    随着IT技术的飞速发展,网络通信技术的应用,使得ERP系统的以实现对整个供应链信息进行集成管理。ERP系统应用客户/服务器(C/S)体系结构和分布式数据处理技术,支持Internet/Intranet/Extranet、电子商务(E-busincss,E-commerce)、电子数据交换EDI,此外,还能实现在不同平台上的互操作。我们就讨论了路标的概念,当你的第一个路标达成之后,剩下的应该都是属于校订的事了。通过和用户的交互,确定新的路标,不断的改进系统功能,优化系统结构,修正系统Bug

    通过使用WWF,你可以创建基于处理器流的工作流并且把它们部署在任何类型的.NET应用程序中。此外,本文还讨论了ASP.NET开发者面对的一些特有的问题-这些问题可能通过使用工作流得到解决,如维持状态和页面导航等。

    8. WWFWindows工作流基础是什么?14875e45bb©应届

    答:在20059月,微软在它的一年两次的专业开发者会议上公开了Windows Workflow Foundation(WWFWindows工作流基础)。作为WinFX API的支柱之一,WWF提供给开发者一个普通框架-在其上开发过程驱动的和以工作流为中心的应用程序。

    当前,有些组织力图把整个商业过程自动化;他们的标准答案就是集合一队开发者来开发相应的代码。尽管这种方式对于这些组织带来良好的作用,然而也有一些固有的问题。为了深入理解这一问题,你需要理解一个工作流的基本特征。

    一个工作流本质是一种方法-用来归档包含在完成一个单元的工作中的活动。典型地,在处理过程中,工作""流过一项或更多活动。这些活动可以通过机器或人工来实现,并且有可能象在一个互联网应用程序定义页面顺序一样得简单,也有可能象管理必须为任何数目的人都要看到、更改并同意的文件或产品一样得复杂。976aab5298©应届生ingJieSheng.COM©5ebbcd 3a 1b

    因为如此多的工作流程必须考虑到人工参预,所以可能需要花费很长工期才能完成,时间可能为几小时到数月或更长。例如,参预在该过程中的人可能无法找到,不在本地或忙于另外的任务;因此,工作流必须在所有非活动期间能够把自身持续性存储。而且,通过编码独立实现的过程可能对非技术人员难于理解而对开发者却难于更改。这一点和其它一些因素正是例如Windows WF等通用工作流框架的目标-其目的就在于使创建、改变和管理工作流更容易-这是通过向它们提供一个可视化接口或通过定义一组普通API来实现的。

    你可以把WWF工作流放置在任何类型的.NET应用程序中-包括Windows表单程序,控制台应用程序,Windows服务和ASP.NET Web应用程序。每种类型都需要专门的考虑。尽管一些现有示例已经足够说明如何把工作流宿主到Windows表单程序和控制台应用程序中,但是本文将集中于讨论ASP.NET开发者的问题-他们希望把工作流集成到自己的应用程序中。

    Windows WFMVC模式:在开发一个ASP.NET应用程序时,你可能使用WWF的一个普通的方法是实现一种模型-视图-控制器(MVC)方法。实质上,MVC的目标是把描述层、应用程序逻辑和应用程序流逻辑分离开来。应届生

    搞清楚这个将十分有益于一个ASP.NET应用程序的开发,请考虑一个帮助桌面票工作流的场所。假定有一个商业用户通过填写一个ASP.NET Web表单并点击一个提交按钮来启动该工作流。接下来,服务器就会通知一个使用Windows表单应用程序和帮助桌面的雇员—“有新票可用了。该帮助桌面雇员然后将在这一问题上工作,并在最后关闭该票。如果使用Windows WF来开发这个工作流情形,那么所有的处理逻辑和流程可以被包含在工作流本身,而该ASP.NET应用程序将完全不需要了解这一逻辑。

    这种场所提供了一些稳固的证据-把描述与逻辑相分离是一件好事情。因为这个处理帮助桌面请求的过程是非常普通的,如果使用C#VB.NET代码在若干不同的.NET应用程序中实现这一逻辑,那么你将会冒着重复编码的危险甚至更坏的情形--用完全不同的代码导致同样的商业处理过程的不同实现。但是如果你使用WWF来实现这一过程,那么需要这一过程的应用程序开发者将仅需在一处修改这些步骤-工作流本身-而不必担心这样会改变应用程序逻辑。代码复制和在哪里实现该过程可以通过Windows WF的使用来加以缓和。

    当使用Windows WFASP.NET中实现MVC架构时,开发者应该尝试构建独立于应用程序的工作流-而该工作流仍然宿主于该应用程序中。这将有助于保持逻辑独立于描述并且保持在该Web应用程序中的工作步骤顺序和页面流之间的高度独立性。65e6e1edc0©应届ingJieSheng.COM©c241e73e84

    一个WWF开发新手可能试图用一固定数目的活动以某种顺序去开发一个工作流,然后开发一组ASP.NET Web表单--这些表单以与之相同的顺序从一个表单流向另一个表单。很遗憾,尽管这看上去挺符合逻辑,但是实际上这是非常不具有生产效率的,因为你将会再次实现这个工作流逻辑。Web页面X不需要知道是否它需要转到页面Y或页面Z来正确地实现该工作流步骤。代之的是,该工作流(模型)应该告诉ASP.NET(控制器)下一步该干什么;然后ASP.NET应该决定要显示哪个页面。这样,每个页面几乎不需要了解整个过程;它仅需要知道怎样完成一个不同的活动并且让该工作流来关心页面是如何从一处流向另一处的。这种分离在开发者处理页面流时带来了一种极大的灵活性。例如,如果你决定改变该页面显示顺序,那么你可以从工作流中容易地实现这一点,而不需要改变该ASP.NET应用程序中的一行代码。

    9. 陈述一下软件架构的概念

    :软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口_(计算机科学)来实现。68b6edd301©应届生YingJie

    软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。

    软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。

    软件构架简介中,David GArlan Mary Shaw 认为软件构架是有关如下问题的设计层次:在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”[GS93]94728bc应届生求职网

    但构架不仅是结构;IEEE Working Group on Architecture 把其定义为系统在其环境中的最高层概念”[IEEE98]。构架还包括符合系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即同时注重对外部的考虑。

    Rational Unified ProcESs 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互。

    从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。一个软件架构师需要有广泛的软件理论知识和相应的经验来事实和管理软件产品的高级设计。软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。fc03eb9deingJieSheng.COM©0b322dacbb

    10. 软件系统的架构(ArchitECture)有两个要素是什么?

    答:1) 它是一个软件系统从整体到部分的最高层次的划分。c49eb7©应届生

    一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。

    详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(TASk-flow)。所谓架构元素,也就是组成系统的核心"砖瓦",而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。

    2) 建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定。在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过非常慎重的研究和考察。

    卡内基梅隆大学和加州大学埃尔文分校在这个领域作了很多研究。卡内基·梅隆大学的Mary ShawDavid Garlan1996年写了一本叫做 Software Architecture perspective on an emerging DIscipline的书,提出了软件架构中的很多概念,例如软件组件、连接器、风格等等。 加州大学埃尔文分校的软件研究院所做的工作则主要集中于架构风格、架构描述语言以及动态架构。

    11. 架构的目标是什么f9020d2abe©

    答:要达到如下的目标:

    ·可靠性(Reliable)。软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。

    ·安全行(Secure)。软件系统所承担的交易的商业价值极高,系统的安全性非常重要。ccbdb62ec9©应届生求职网YingJieSheng.COM©1cf 9f 0fcd1

    ·可扩展性(SCAlable)。软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩展得可能性。

    ·可定制化(CuSTomizable)。同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。

    ·可扩展性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展787bd1©应届生求职网

    ·可维护性(MAIntainable)。软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费

    ·客户体验(Customer Experience)。软件系统必须易于使用。

    ·市场时机(Time to Market)。软件用户要面临同业竞争,软件提供商也要面临同业竞争。以最快的速度争夺市场先机非常重要。

    12. 什么是构架风格

    答:软件构架(或仅是构架视图)可以具有名为构架风格的属性,该属性减少了可选的形式,并使构架具有一定程度的一致性。样式可以通过一组模式或通过选择特定构件或连接器作为基本构件来定义。对给定系统,某些样式可作为构架描述的一部分记录在构架风格指南(Rational Unified Process 中设计指南文档的一部分)中。样式在构架的可理解性与完整性方面起着主要的作用。

    13. 什么是构架设计图 ?有哪些组成?74270fd093©应届生

    答:构架视图的图形描述称为构架设计图。对于以上描述的各种视图,设计图由以下统一建模语言图组成 [UML99]

    逻辑视图:类图、状态机和对象图。

    进程视图:类图与对象图(包括任务 - 进程与线程)。9d

    实施视图:构件图。

    部署视图:配置图。

    用例视图:用例图描述用例、主角和普通设计类;顺序图描述设计对象及其协作关系。d7dbbgJieSheng.COM©4bc016b14b

    14. 谈谈构架设计流程。

    答:在 Rational Unified Process 中,构架主要是分析设计工作流程的结果。当项目再次进行此工作流程时,构架将在一次又一次迭代中不断演化、改进、精炼。由于每次迭代都包括集成和测试,所以在交付产品时,构架就相当强壮了。构架是精化阶段各次迭代的重点,构架的基线通常会在此阶段结束时确定。

     

    展开全文
  • Oracle 数据库实例介绍

    万次阅读 多人点赞 2018-11-23 15:44:13
    本章介绍 Oracle 数据库实例的原理,实例的参数文件和诊断文件,以及实例创建和数据库的打开与关闭的过程。

    文章翻译源于 Oracle Database Database Concepts, 18c

    本章介绍 Oracle 数据库实例的原理,实例的参数文件和诊断文件,以及实例创建和数据库的打开与关闭的过程。

    本章包含以下内容:

    • 数据库实例介绍
    • 实例启动与关闭
    • 检查点
    • 实例恢复
    • 参数文件
    • 诊断文件

    数据库实例介绍

    数据库实例(instance)是一组用于管理数据库文件的内存结构。

    数据库是一组位于磁盘上的物理文件,通过 CREATE DATABASE 语句创建。实例管理相关的数据,并且为数据库用户提供服务。

    每个正在运行的 Oracle 数据库至少与一个实例相关联。因为实例存在于内存中,而数据库存在磁盘上,所以实例可以独立于数据库存在,数据库也可以独立于实例存在。

    实例结构

    当一个实例启动时,Oracle 数据库分配一个称为系统全局区(SGA)的内存区域,并启动一个或多个后台进程。

    SGA 的作用包括:

    • 维护多个进程和线程并发访问的内部数据结构
    • 缓存从磁盘读取的数据块
    • 在写入在线重做日志文件之前缓冲重做数据
    • 存储 SQL 执行计划

    同一个服务器上的 Oracle 进程之间共享 SGA。Oracle 进程与 SGA 的交互方式取决于操作系统。

    一个数据库实例包括多个后台进程(background process)。服务器进程(server process),以及分配给它们的内存,也位于实例之中。实例在服务器进程结束后仍然继续存在。

    下图显示了 Oracle 数据库实例中的主要组件。
    Database Instance
    图 13- 1 数据库实例

    实例配置

    Oracle 数据库支持单实例配置和真正应用集群(Oracle RAC)配置。这两种配置只能二选其一。

    在单实例配置中,数据库和实例之间一一对应。在 Oracle RAC 中,数据库和实例存在一对多的关系。

    下图显示了两种可能的数据库实例配置。
    Database Instance Configurations
    图 13-2 数据库实例配置

    无论是单实例还是 Oracle RAC 配置,一个实例每次只能与一个数据库关联。管理员可以启动一个实例,然后加载(关联)一个数据库,但是不能同时加载两个数据库。

    注意:除非特别指出,本章讨论单实例数据库配置。

    一台服务器上可以同时运行多个实例,每个实例管理各自的数据库。例如,某台服务器上拥有两个不同的数据库:prod1 和 prod2。一个实例管理 prod1另一个实例管理 prod2。

    读写实例与只读实例

    实例支持两种模式:读写实例与只读实例。

    对于读写实例,可以处理 DML 操作,支持客户端的直接连接请求。这是默认方式。与此相反,只读实例能够运行查询,但是不能支持 DML修改操作(UPDATE、DELETE、INSERT 以及 MERGE),也不能从客户端直接进行连接。

    注意:除非另外指明,本文档中的实例都是指读写实例。

    在之前的版本中,所有的实例(除非管理一个 standby 数据库)都是读写实例。从 Oracle 数据库 12c (12.2) 开始, 一个数据库可以同时存在只读实例和读写实例。这种配置对于即查询数据又修改数据库的并行 SQL 语句非常有用,因为读写实例和只读实例都能够查询数据,而读写实例能够修改数据。

    与读写实例相比,只读实例具有以下特点:

    • 只能打开一个已经被读写实例打开的数据库
    • 禁用了许多不必要的后台进程,包检查点进程和归档进程
    • 可以加载一个被禁用的重做线程或者没有任何在线重做日期的线程

    要想将实例设置为只读模式,可以将初始化参数 INSTANCE_MODE 设置为 READ_ONLY。该参数的默认值为 READ_WRITE。

    实例生命周期

    数据库实例从 STARTUP 命令创建开始,直到被终止时结束。

    在此期间,一个实例能且只能与一个数据库相关联。进一步而言,该实例只能加载数据库一次、打开数据库一次,并且关闭数据库一次。在数据库关闭之后,必须重新启动一个实例,然后加载并打开数据库。

    下表演示了一个实例尝试重新打开之前关闭的数据库的过程。

    表 13- 1 实例生命周期

    语句注释
    SQL> STARTUP
    ORACLE instance started.
    Total System Global Area 468729856 bytes
    Fixed Size 1333556 bytes
    Variable Size 440403660 bytes
    Database Buffers 16777216 bytes
    Redo Buffers 10215424 bytes
    Database mounted.
    Database opened.
    STARTUP 命令创建一个实例,然后加载并打开数据库。
    SQL> SELECT
    TO_CHAR(STARTUP_TIME,‘MON-DD-RR HH24:MI:SS’)
    AS “Inst Start Time” FROM V$INSTANCE;

    Inst Start Time
    ------------------
    JUN-18-14 13:14:48
    该查询显示了当前实例的启动时间。
    SQL> SHUTDOWN IMMEDIATE关闭数据库和实例,结束实例的生命周期。
    SQL> STARTUP
    Oracle instance started… . .
    STARTUP 命令创建一个新的实例,然后加载并打开数据库。
    SQL> SELECT
    TO_CHAR(STARTUP_TIME,‘MON-DD-RR HH24:MI:SS’)
    AS “Inst Start Time” FROM V$INSTANCE;

    Inst Start Time
    ------------------
    JUN-18-14 13:16:40
    该查询显示了当前实例的启动时间。不同的启动时间表明了这是一个新的实例。

    实例标识

    一个主机上可以运行多个数据库实例。因此,访问时需要指定访问哪个实例。

    Oracle 最优灵活体系结构(OFA)规则是一组配置指南,可以确保组织良好的 Oracle 软件安装。本节中的示例使用 OFA 体系结构。

    本节包含以下主题:

    • Oracle 根目录
    • Oracle 主目录
    • Oracle 系统标识符(SID)

    Oracle 根目录

    Oracle 根目录(Oracle Base directory)存储 Oracle 产品的二进制文件。

    Oracle 根目录是 Oracle 数据库安装拥有者的数据库主目录。一个主机上可以按照多个 Oracle 数据库,以及多个 Oracle 数据库软件安装的拥有者。

    以下示例显示了操作系统用户 oracle 的 Oracle 根目录:

    /u01/app/oracle
    

    在路径的前缀中, /u01/ 是存储的挂载点, /u01/app/ 是安装应用软件的分支目录。

    Oracle 主目录

    Oracle 主目录(Oracle home directory)是 Oracle 数据库软件的安装位置。

    每个新的 Oracle 数据库软件安装都需要指定一个新的 Oracle 主目录。默认情况下,Oracle 主目录是 Oracle 根目录(ORACLE_BASE)下的一个子目录。

    在同一个主机上,相同的 Oracle 根目录下,可以安装不同版本的数据库软件。归属于不同系统用户的不同版本的多个数据库可以并存。

    以下示例显示了三个不同的 Oracle 主目录的完整路径名称,它们都位于相同的 Oracle 根目录(/u01/app/oracle/)下:

    /u01/app/oracle/product/12.1.0/dbhome_1
    /u01/app/oracle/product/12.1.0/dbhome_2
    /u01/app/oracle/product/18.0.0/dbhome_1
    

    路径名称中, Oracle 根目录(/u01/app/oracle/)之后的部分包含了产品版本编号(例如 12.1.0)和 Oracle 主目录的相对路径(例如 dbhome_1)目录 /u01/app/oracle/product/12.1.0/ 中包含了两个不同的 Oracle 主目录: dbhome_1 和 dbhome_2。

    从 Oracle Database 18c 开始,支持创建只读的 Oracle 主目录,将其作为一个软件的映像。只读 Oracle 主目录存储静态文件,例如二进制程序。Oracle 根主目录(ORACLE_BASE_HOME)位于 ORACLE_BASE/homes/home_name,存储与特定 Oracle 主目录相关的动态文件。Oracle 根配置目录(ORACLE_BASE_CONFIG)由 Oracle 根目录中的所有 Oracle 主目录共享,用于存储实例相关的动态文件。

    以下示例中,第一个路径是一个只读 Oracle 主目录,第二个路径是其对应的 根主目录:

    /u01/app/oracle/product/18.0.0/ro_dbhome_1
    /u01/app/oracle/homes/ro_dbhome_1
    

    Oracle SID

    系统标识符(SID) 是一个主机上的 Oracle 数据库实例的唯一名称。

    在 UNIX 和 Linux 系统上,Oracle 数据库使用 SID 和 Oracle 主目录的路径名称作为共享内存的键值。 另外,Oracle 数据库默认使用 SID 查找初始化参数文件,通过初始化文件查找其他相关文件,例如数据库控制文件。

    在大多数平台上,使用 ORACLE_SID 环境变量设置 SID,使用 ORACLE_HOME 变量设置 Oracle 主目录。客户端连接数据库实例时,可以在 Oracle Net 连接中指定 SID,或者使用一个网络服务名(service name)。 Oracle 数据库将服务名转换为 ORACLE_HOME 和 ORACLE_SID。

    传统的可读写 Oracle 主目录包含了实例相关的文件。但是,如果 Oracle 主目录改为只读,实例相关的文件单独存储在 Oracle 根目录中。无论哪种情况,名称中包含 SID 的文件存储在 Oracle 主配置目录(ORACLE_BASE_CONFIG)的 dbs 子目录中。有了这种文件分离,用户可以使用只读 Oracle 主目录中的软件创建数据库,然后使用另一个只读 Oracle 主目录中的软件启动一个实例,管理该数据库。

    实例启动与关闭

    数据库实例(database instance)为用户提供数据库访问。实例和数据库存在各种不同的状态。

    启动实例与数据库

    通常来说,管理员手动启动一个实例,然后加载并打开数据库,接受客户端连接。这些操作可以通过 SQL*Plus 的 STARTUP 命令、 Oracle 企业管理器(Enterprise Manager)或者 SRVCTL 工具完成。

    如果使用 Oracle Net 启动一个数据库实例,需要满足以下条件:

    • 数据库通过静态方式注册到 Oracle Net 监听器中。
    • 使用 SYSDBA 权限进行连接。

    监听器启动一个专用的服务器进程,用于启动数据库实例。

    下图显示了数据库从关闭到打开的处理过程。
    Instance and Database Startup Sequence
    图 13-3 实例与数据库启动顺序

    数据库从关闭状态到打开状态需要经历以下几个阶段。

    表 13-2 实例启动阶段

    阶段加载状态描述更多内容
    1启动实例,未加载数据库启动一个实例,但没有与数据库关联。启动实例
    2加载数据库实例已经启动,并且读取数据库的控制文件。数据库对用户不可用。加载数据库
    3打开数据库实例已经启动,并且打开数据库。授权用户可以访问数据文件中的数据。打开数据库

    管理员登录

    数据库的启动和关闭是非常强大的管理功能,只能由具有管理员权限的用户执行。

    普通用户无法控制数据库的当前状态。根据操作系统的不同,用户可以通过以下方式获得管理员权限:

    • 用户的操作系统权限允许他/她已管理员权限连接到数据库。
    • 用户被授予特殊的系统权限,数据库使用口令文件认证通过网络连接的管理员

    以下特殊的系统权限能够在数据库未打开时访问实例:

    • SYSDBA
    • SYSOPER
    • SYSBACKUP
    • SYSDG
    • SYSKM

    以上权限的管理不在数据库的自身范围之内。使用 SYSDBA 系统权限连接时,用户位于 SYS 模式中。使用 SYSOPER 连接时,用户位于公共模式中。SYSOPER 权限是 SYSDBA 权限的一个子集。

    启动实例

    当 Oracle 数据库启动一个实例时,需要经过几个阶段。

    实例启动阶段包括:

    1. 查找不同平台下默认位置中的服务器参数文件,如果没有找到该文件,查找文本形式的初始化参数文件(在 STARTUP 命令中指定 SPFILE 或 PFILE 参数将会覆盖默认行为)
    2. 读取参数文件,获取初始化参数的值
    3. 基于初始化参数设置分配 SGA
    4. 启动 Oracle 后台进程
    5. 打开告警日志(alert log)文件和跟踪文件(trace file),按照参数设置的语法在告警日志中写入所有显式指定的参数设置

    在这一阶段,实例还没有关联到数据库。NOMOUNT 状态的使用场景包括数据库创建以及备份与恢复操作。

    加载数据库

    实例通过加载数据库与其进行关联。

    加载数据库时,实例通过初始化参数 CONTROL_FILES 获取数据库控制文件 的名称并打开这些文件。Oracle 数据库读取控制文件,获取数据文件和在线重做日志文件的名称,在打开数据库时需要访问这些文件。

    加载之后,数据库处于关闭状态,只允许管理员访问。管理员可以在保持数据库关闭的同时执行一些特定的维护操作。但是,此时数据库还不能执行一些常规操作。

    如果 Oracle 数据库允许多个实例同时加载相同的数据库,初始化参数 CLUSTER_DATABASE 可以设置多个实例访问该数据库。具体的行为取决于该参数的值:

    • 如果第一个加载数据库的实例的 CLUSTER_DATABASE 设置为 false(默认值),只有该实例能够加载数据库。
    • 如果第一个加载数据库的实例的 CLUSTER_DATABASE 设置为 true,其他实例在 CLUSTER_DATABASE 也设置为 true 时可以加载该数据库。可以同时加载同一个数据库的实例数量由创建数据库时的预定义值决定。

    打开数据库

    打开一个已加载的数据库意味着可以对其执行常规的操作。

    任何有效的用户都可以连接到一个打开的数据库,并且访问其中的信息。通常来说,数据库管理员负责打开数据库。

    打开数据库时, Oracle 数据库将会执行以下操作:

    • 打开撤销表空间(undo tablespace)之外的其他表空间的在线数据文件

      如果一个表空间在数据库关闭之前处于离线(offline)状态,重新打开数据库时,该表空间和相应的数据文件仍然处于离线状态。

    • 获取一个撤销表空间

      如果存在多个撤销表空间,由初始化参数 UNDO_TABLESPACE 决定使用哪个表空间。如果没有设置该参数,使用第一个可用的撤销表空间。

    • 打开在线重做日志文件

    只读模式

    默认情况下,数据库以读/写模式打开。在这种模式下,用户可以修改数据,产生重做日志项。另外,数据库可以以只读模式打开,防止用户事务修改数据。

    注意:默认情况下,物理备用数据库以只读模式打开。

    只读模式下的数据库只能执行只读事务,不能写入数据文件或者在线重做日志文件。不过,数据库仍然能够执行恢复操作或者不产生重做日志的操作。例如,只读模式支持以下操作:

    • 将数据文件离线或者在线。但是,不能将永久表空间离线。
    • 恢复离线的数据文件和表空间。
    • 修改控制文件中关于数据库状态的信息。
    • 使用 CREATE TEMPORARY TABLESPACE 语句创建的临时表空间允许读写操作。
    • 写入操作系统的审计文件、跟踪文件以及告警日志。
    数据库文件检查

    如果打开数据库时,任何数据文件或重做日志文件不存在,或者它们存在但是一致性检测失败,数据库将会返回一个错误。此时需要执行介质恢复。

    关闭数据库与实例

    通常来说,管理员在执行维护操作或其他管理任务时手动关闭数据库。可以使用 SQL*Plus 的 SHUTDOWN 命令或者 Enterprise Manager 执行这些操作。

    下图演示了数据库从打开状态到一致性关闭的过程。
    Instance and Database Shutdown Sequence
    图 13-4 实例与数据库关闭顺序

    Oracle 数据库从打开到一致性关闭时自动执行以下操作。
    表 13-3 一致性关闭的步骤

    阶段加载状态描述更多内容
    1关闭数据库数据库处于加载状态,但是在线数据文件和重做日志文件被关闭。关闭数据库
    2卸载数据库实例处于启动状态,但是不再关联数据库的控制文件。卸载数据库
    3关闭实例实例被关闭,不再处于启动状态。关闭实例

    Oracle 数据库在出现实例失败或者执行 SHUTDOWN ABORT (立即终止实例)命令时,不会执行以上操作。

    关闭模式

    具有 SYSDBA 或者 SYSOPER 权限的数据库管理员可以使用 SQL*Plus 的 SHUTDOWN 命令或 Enterprise Manager 关闭数据库。SHUTDOWN 命令包含了不同的关闭选项。

    下表总结了不同的关闭模式。
    表 13-4 数据库关闭模式

    数据库行为ABORTIMMEDIATETRANSACTIONALNORMAL
    运行新用户连接
    等待当前会话结束
    等待当前事务结束
    执行检查点并关闭打开的文件

    不同的 SHUTDOWN 语句包括:

    • SHUTDOWN ABORT

      这种关闭模式用于紧急情况,例如其他模式无法关闭实例时。这种模式速度最快。但是,随后再打开数据库时需要更长的时间,因此需要执行实例恢复以确保数据文件的一致性。

      由于 SHUTDOWN ABORT 命令不对打开的数据文件执行检查点操作,重新打开数据库时必须执行实例恢复。其他的关闭模式在重新打开数据库时不需要执行实例的恢复。

      注意:在 CDB 中,针对 PDB 执行的 SHUTDOWN ABORT 命令等价于非 CDB 上的 SHUTDOWN IMMEDIATE 命令。

    • SHUTDOWN IMMEDIATE

      这种关闭模式是除了 SHUTDOWN ABORT 之外的最快方式。Oracle 数据库立即终止任何正在执行的 SQL 语句并且断开用户的连接。系统终止所有正在进行的事务,并且回滚未提交的更改。

    • SHUTDOWN TRANSACTIONAL

    这种关闭模式不允许用户开始新的事务,但会等待所有当前正在执行的事务结束,然后关闭数据库。这种模式可能需要等待很长的时间才能完成。

    • SHUTDOWN NORMAL

    这是默认的关闭模式。数据库在关闭之前等待所有连接的用户断开连接。

    关闭数据库

    关闭数据库的操作分为正常关闭和异常关闭。

    正常关闭

    当数据库使用非 ABORT 模式关闭时,会将 SGA 中的数据写入数据文件和在线重做日志文件。

    然后,数据库关闭在线数据文件和重做日志文件。离线表空间中的离线数据文件已经处于关闭状态。当数据库重新打开时,原来的离线表空间仍然处于离线状态。

    此时,数据库已经关闭,不接受正常访问。但是控制文件仍然处于打开状态。

    异常关闭

    如果使用 SHUTDOWN ABORT 命令关闭数据库或者数据库异常终止时,实例瞬间停止并关闭数据库。

    异常关闭时,Oracle 数据库不会将 SGA 缓存中的数据写入数据文件和重做日志文件。随后重新打开数据库时需要执行实例恢复,Oracle 自动执行实例的恢复操作。

    卸载数据库

    在关闭数据库之后,Oracle 将会卸载数据库,将其与实例分离。

    卸载数据库之后,Oracle 关闭数据库的控制文件。此时,实例仍然存在于内存之中。

    关闭实例

    关闭数据库的最后一步就是关闭实例。关闭实例时,系统释放 SGA 内存,并停止后台进程。

    在异常情况下,实例可能没有关闭干净。内存中仍然存在一些内存结构,或者某个后台进程仍未终止。如果之前的实例仍然部分存在,后续的实例可能会启动失败。此时,可以通过删除之前实例的残余并重新启动一个新实例,或者使用 SHUTDOWN ABORT 语句关闭之前的实例,强制启动一个新的实例。

    某些情况下,进程的清除可能会遇到错误,导致进程监控进程(PMON)或者实例的终止。动态初始化参数 INSTANCE_ABORT_DELAY_TIME 用于指定发生内部实例失败时延迟关闭的时间(秒)。延迟时间之内,管理员可以介入处理。当发生延迟的实例终止时,数据库在告警日志中写入一条消息。某些情况下,通过允许隔离某些数据库资源,可以避免实例被终止。

    检查点

    检查点(checkpoint)对于一致性数据库关闭、实例恢复以及常规数据库操作都至关重要。

    检查点操作具有以下含义:

    • 检查点位置(checkpoint position),它表示重做日志流中的系统更改号(SCN),实例恢复必须从该检查点位置开始

      检查点位置由数据库缓冲区高速缓存中最早的脏块决定。检查点位置相当于一个指向重做流的指针,它的信息存储在控制文件以及每个数据文件的头部。

    • 将数据库缓冲区高速缓存中被修改过的缓存数据写入磁盘

    检查点的作用

    Oracle 数据库使用检查点实现多个功能,包括:

    • 减少实例或介质失败时的恢复时间
    • 确保数据库定期将缓冲区高速缓存中的脏数据写入磁盘
    • 确保数据库在一致性关闭时将所有已提交的数据写入磁盘

    检查点触发时机

    检查点进程(CKPT)负责将检查点写入数据文件头部以及控制文件中。

    许多场景都会导致检查点发生。例如,Oracle 数据库包含以下检查点类型:

    • 线程检查点

      数据库在完成特定操作之前将某个重做线程修改的缓存数据写入磁盘。一个数据库的所有实例上的线程检查点集合组成数据库检查点。线程检查点在以下情况下触发:

      • 一致性数据库关闭
      • 执行 ALTER SYSTEM CHECKPOINT 语句
      • 在线重做日志切换
      • 执行 ALTER DATABASE BEGIN BACKUP 语句
    • 表空间和数据文件检查点

    数据库在完成特定操作之前将所有重做线程修改的缓存数据写入磁盘。表空间检查点包含一组数据文件检查点,每个数据文件一个检查点。这些检查点的触发事件包括:将表空间设置为只读或者正常离线,收缩数据文件,或者执行 ALTER TABLESPACE BEGIN BACKUP 命令。

    • 增量检查点

    增量检查点是一种线程检查点,作用包括避免在线重做日志切换时的大量数据块写入。DBW 至少每三秒执行一次检查,判断是否需要写入数据。当 DBW 将脏缓存写磁盘时,同时推进检查点位置,使得 CKPT 将检查点位置写入控制文件,但不会写入数据文件头部。

    其他类型的检查点包括实例与介质恢复检查点,以及删除或截断模式对象时的检查点。

    实例恢复

    实例恢复(Instance recovery)是将在线重做日志文件中的记录应用到数据文件的过程,用于重建最近的检查点之后的数据变更。

    当管理员尝试打开一个之前未能一致性关闭的数据库时,系统自动执行实例的恢复。

    实例恢复的作用

    实例恢复可以确保数据库在发生实例失败之后能够恢复到一致性的状态。数据对于变更的管理方式,导致数据库文件可能会处于一个非一致性的状态。

    日志线程(redo thread)是一个实例产生的所有变更记录。单实例数据库只有一个日志线程,而 Oracle RAC 数据库包含多个日志线程,每个实例一个日志线程。

    当事务被提交时,日志写入进程(LGWR)将内存中的重做日志项和该事务的 SCN 同时写入在线重做日志。但是,数据写入(DBW)进程以系统认为的高效方式将修改后的数据块写入数据文件。因此,未提交的更改可能会临时存在数据文件中,同时已提交的修改有可能未写入数据文件。

    如果数据库位于打开状态时发生实例失败(可能是由于 SHUTDOWN ABORT 语句或异常终止),将会导致以下状况:

    • 已提交的数据块还没有写入数据文件,只记录在在线重做日志中。这些变更必须重新应用到数据文件中。
    • 数据文件中包含一些实例失败时未提交的变更。这些变更必须进行回滚,以确保事务的一致性。

    实例恢复只利用在线重做日志文件和当前在线数据文件执行数据文件的同步,确保它们的一致性。

    实例恢复的时间

    是否需要执行实例恢复取决于日志线程的状态。

    当数据库实例以读写模式打开时,对应的日志线程被标记为打开状态,当实例一致性关闭时,日志线程被标记为关闭。如果日志线程在控制文件中是打开状态,但是没有对应的活动实例,数据库需要执行实例恢复。

    Oracle 数据库在以下情况下自动执行实例恢复:

    • 单实例数据库失败后,或者 Oracle RAC 数据库的所有实例失败后,首次打开数据库。这种形式的实例恢复也称为崩溃恢复。Oracle 数据库同时恢复所有失败实例的在线重做日志线程。
    • Oracle RAC 数据库的部分(非全部)实例失败 。集群中某个存活实例自动执行实例恢复操作。

    后台进程 SMON 负责执行实例恢复,自动应用在线重做日志。整个过程不需要管理员介入。

    检查点的重要性

    实例恢复时,使用检查点决定需要应用到数据文件中的变更。检查点位置确保了所有 SCN 小于检查点 SCN 的已提交变更都已保存到数据文件中。

    下图描绘了在线重做日志中的日志线程。
    Checkpoint Position in Online Redo Log
    图 13-5 在线重做日志中的检查点位置

    在执行实例恢复时,数据库必须应用检查点位置和日志线程终点之间的所有变更。如图 13-5 所示,某些变更可能已经写入了数据文件。但是,只有 SCN 小于检查点位置的变更确认已经写入磁盘之中。

    实例恢复步骤

    实例恢复的第一步称为缓存恢复(cache recovery)或前滚(rolling forward),将在线重做日志中的所有变更重新应用到数据文件中。

    由于在线重做日志中包含了撤销数据(undo data),前滚操作也会重建相应的撤销段(undo segment)。前滚操作应用在线重做日志文件将数据库恢复到实例失败之前的状态。完成前滚操作之后,数据块中包含了在线重做日志文件中的所有已提交变更。这些数据文件中可能还包含一些实例失败之前写入的未提交变更,或者缓存恢复时从在线重做日志中引入的未提交变更。

    前滚之后,未提交的变更需要回滚。Oracle 数据库使用检查点位置确保所有 SCN 小于检查点 SCN 的已提交变更已经写入磁盘。Oracle 数据库应用撤销块 回滚未提交的变更(包括实例失败之前写入的变更和缓存恢复时引入的变更)。这个阶段称为回滚(rolling back)或者事务恢复(transaction recovery)。

    下图演示了数据库实例恢复的两个必要步骤:前滚和回滚。
    Basic Instance Recovery Steps: Rolling Forward and Rolling Back
    图 13-6 基本实例恢复操作:前滚和回滚

    Oracle 数据库可以根据需要同时回滚多个事务。实例失败时的所有活动事务都被标记为终止。新的事务可以回滚各自的数据块以获取所需的数据,而不需要等待 SMON 进程回滚被终止的事务。

    参数文件

    启动数据库实例时,Oracle 数据库必须读取一个服务器参数文件(推荐方式)或者一个文本初始化参数文件(传统遗留方式)。这些文件中包含了一个配置参数的列表。

    手动创建一个数据库时,必须使用一个参数文件启动实例,然后执行 CREATE DATABASE 语句。实例和参数文件可以独立于数据库而存在。

    初始化参数

    初始化参数(Initialization parameter)是一些可以影响实例操作的配置参数。实例在启动时读取参数文件中的初始化参数。

    Oracle 数据库提供了许多初始化参数,用于优化不同环境下的操作。只有少数参数需要显式设置,通常只需要使用默认值即可。

    初始化参数分组

    初始化参数可以按照功能分为不同的组。

    大部分初始化参数属于以下分组之一:

    • 设置实体项目(例如文件或目录)的参数
    • 设置进程限制、数据库资源限制、或者数据库自身限制的参数
    • 影响容量的参数,例如 SGA 的大小(这些参数被称为可变参数)

    数据库管理员特别关注可变参数,因为他们可以通过这些参数优化数据库的性能。

    基本参数与高级参数

    初始化参数可以分为两类:基本参数和高级参数。

    通常来说,管理员需要设置并优化大约 30 个基本的参数,以达到合理的性能。基本参数用于设置一些特性,例如数据库名称、控制文件的位置、数据库块大小以及撤销表空间。

    在极少数情况下,管理员需要修改高级参数,以便获得最佳性能。DBA 专家通过可以高级参数调整数据库的行为,以满足特定的需求。

    Oracle 数据库在安装软件的启动初始化参数文件中提供了参数值,或者可以通过数据库配置助手(DBCA)创建这些参数。管理员可以根据自己的配置需求或者调优方案,修改 Oracle 提供的这些初始化参数,也可以增加其他参数。对于参数文件中没有涉及的相关初始化参数,Oracle 数据库提供默认值。

    服务器参数文件

    服务参数文件(server parameter file)是初始化参数的一个存储库。

    服务器参数文件具有以下主要特征:

    • 只能由 Oracle 数据库读写服务器参数文件。
    • 一个数据库只能有一个服务器参数文件。该文件必须存放在数据库服务器主机中。
    • 服务器参数文件是一个二进制文件,不能使用文本编辑器进行修改。
    • 服务器参数文件中的初始化参数是永久存储的。在数据库实例运行时对参数所做的任何更改在实例关闭和启动后仍然生效。

    服务器参数文件使得客户端应用不再需要维护多个文本初始化参数文件。服务器参数文件通过 CREATE SPFILE 语句从文本初始化参数文件创建。它可以通过数据库配置助手直接创建。

    文本初始化参数文件

    文本初始化参数文件(text initialization parameter file)是一个文本文件,内容是一个初始化参数的列表。

    这种参数文件是历史遗留的实现方式,它具有以下主要特点:

    • 当启动或者关闭数据库时,文本初始化参数文件必须位于连接到数据库的客户端主机中。
    • 文本初始化参数文件时一个文本文件,而不是二进制文件。
    • Oracle 数据库可以读取文本初始化参数文件,但是不能写入该文件。要想修改参数的值,必须通过文本编辑器手动进行修改。
    • 使用 ALTER SYSTEM 语句修改的初始化参数值只在当前实例中生效。必须手动更新文件初始化参数文件并重启实例才能永久生效。

    文本初始化参数文件中包含一系列 key=value 配置,每行一个配置。例如,以下是某个参数文件中的部分内容:

    db_name=sample
    control_files=/disk1/oradata/sample_cf.dbf
    db_block_size=8192
    open_cursors=52
    undo_management=auto
    shared_pool_size=280M
    pga_aggregate_target=29M
    .
    .
    .
    

    为了说明文本参数文件可能带来的管理问题,假设你使用了计算机 clienta 和 clientb,并且需要能够从任意一个计算机上启动数据库。此时,每个计算机上都需要一个单独的文本初始化参数文件,如图 13-7 所示。 服务参数文件可以解决参数文件的分散存储问题。
    Multiple Initialization Parameter Files
    图 13-7 多个初始化参数文件

    修改初始化参数

    管理员可以通过修改初始化参数来调整数据库的行为。参数按照修改方式分为静态(static)参数和动态(dynamic)参数。

    下列表格总结了它们的不同之处。

    表 13-5 静态初始化参数和动态初始化参数

    特性静态参数动态参数
    需要修改参数文件
    需要重启实例才能生效
    Oracle Database Reference 中显示为“Modifiable”
    只能修改数据库或实例相关的参数

    静态参数包括 DB_BLOCK_SIZE、DB_NAME 以及 COMPATIBLE。动态参数分为会话级别的参数(只影响当前会话)和系统级别的参数(影响数据库和所有会话)。例如,MEMORY_TARGET 是一个系统级参数,而 NLS_DATE_FORMAT 是一个会话级参数。

    参数变更的范围取决于变更何时生效。当实例使用服务器参数文件启动时,可以使用 ALTER SYSTEM SET 语句选择以下方式修改系统级参数:

    • SCOPE=MEMORY

      参数的变更只针对当前数据库实例生效。数据库关闭并重启后变更不会持久化。

    • SCOPE=SPFILE

      参数的变更只应用于服务器参数文件,不会影响当前实例。因此,变更只在实例重启之后生效。

      注意:对于那些在 Oracle Database Reference 中标识为不可更改的参数,修改时必须指定 SPFILE 。

    • SCOPE=BOTH

      Oracle 数据库同时将变更写入内存和服务器参数文件。这是数据库使用服务器参数文件时的默认修改范围。

    诊断文件

    Oracle 数据库提供了一个故障诊断基础架构(fault diagnosability infrastructure),用于防止、检测、诊断和解决数据库问题。这些问题包括代码错误、元数据损坏以及客户数据丢失等严重错误。

    这个高级的故障诊断基础架构的作用包括:

    • 主动发现问题
    • 检测到问题后控制损失和系统中断
    • 减少故障诊断和解决时间
    • 通过拆分跟踪文件提高可管理性,允许用户指定每个文件的大小,以及保留的最大文件数量,并且在占用的存储到达用户指定的磁盘空间后关闭跟踪
    • 方便客户与 Oracle 支持人员的交流

    多租户容器数据库(CDB)与非 CDB 的诊断架构不同。本节内容针对非 CDB,除非另有说明。

    自动诊断库

    自动诊断库(ADR)是一个基于文件的资料库,用于存储数据库的诊断数据,例如跟踪文件、告警日志、DDL 日志以及健康健康报告。

    ADR 具有以下主要特点:

    • 统一的目录结构
    • 一致的诊断数据格式
    • 统一的工具套件

    以上特性使得客户和 Oracle 支持人员能够关联和分析多个实例、组件和产品的诊断数据。

    ADR 存储在数据库之外,Oracle 数据库在物理库不可用时仍然能够访问和管理 ADR。数据库实例在创建数据库之前创建 ADR。

    问题和事件

    ADR 可以主动发现问题(problems), 它们是数据库中的一些关键错误。

    关键错误显示为内部错误,例如 ORA-600,或者其他严重错误。每个问题拥有一个问题键(problem key),它是描述该问题的文本字符串。

    当一个问题多次发生时,ADR 为每次的错误创建一个包含时间戳的事件(incident)。事件由一个数字的事件 ID 唯一确定。当一个事件发生时, ADR 将会发送一个事件告警(incident alert)到 Enterprise Manager。一个关键错误的诊断和解决通常从一个事件告警开始。

    由于一个问题可能在短时间内产生多次事件,当该事件的次数到达一个特定阈值之后,ADR 将会采用防洪控制措施。防洪控制事件只会产生一个告警日志项,而不会产生事件转储信息。ADR 通过这种方式通知用户正在发生一个严重的错误,而不会因为产生大量的诊断数据给系统带来压力。

    ADR 目录结构

    ADR base 是 ADR 的根目录。

    ADR 根目录下可以存在多个 ADR 主目录(ADR home),每个 ADR 主目录是一个 Oracle 产品或组件的实例的诊断数据所在的根目录,包括跟踪文件、转储文件以及告警日志等等。例如, 在一个使用了共享存储和 Oracle ASM 的 Oracle RAC 环境中,每个数据库实例和 Oracle ASM 实例都拥有各自的 ADR 主目录。

    图 13-8 显示了一个数据库实例的 ADR 目录层次结构。在相同的 ADR 根目录下,还可以存在其他 Oracle 产品或组件的其他 ADR 主目录,例如 Oracle ASM 或者 Oracle Net Services。
    ADR Directory Structure for an Oracle Database Instance
    图 13-8 Oracle 数据库实例的 ADR 目录结构

    以下是一个 Linux 环境的示例,当你在创建数据库之前使用一个唯一的 SID 和数据库名称启动实例时,Oracle 数据库默认在文件系统中创建一个 ADR 目录结构。SID 和数据库名称成为了 ADR 主目录中的文件路径的一部分。

    示例 13-1 创建 ADR

    % setenv ORACLE_SID osi
    % echo "DB_NAME=dbn" > init.ora
    % sqlplus / as sysdba
    .
    .
    . 
    Connected to an idle instance.
     
    SQL> STARTUP NOMOUNT PFILE="./init.ora"
    ORACLE instance started.
     
    Total System Global Area  146472960 bytes
    Fixed Size                  1317424 bytes
    Variable Size              92276176 bytes
    Database Buffers           50331648 bytes
    Redo Buffers                2547712 bytes
     
    SQL> COL NAME FORMAT a21
    SQL> COL VALUE FORMAT a60
    SQL> SELECT NAME, VALUE FROM V$DIAG_INFO;
     
    NAME                  VALUE
    --------------------- --------------------------------------------------------
    Diag Enabled          TRUE
    ADR Base              /d1/3910926111/oracle/log
    ADR Home              /d1/3910926111/oracle/log/diag/rdbms/dbn/osi
    Diag Trace            /d1/3910926111/oracle/log/diag/rdbms/dbn/osi/trace
    Diag Alert            /d1/3910926111/oracle/log/diag/rdbms/dbn/osi/alert
    Diag Incident         /d1/3910926111/oracle/log/diag/rdbms/dbn/osi/incident
    Diag Cdump            /d1/3910926111/oracle/log/diag/rdbms/dbn/osi/cdump
    Health Monitor        /d1/3910926111/oracle/log/diag/rdbms/dbn/osi/hm
    Default Trace File    /d1/3910926111/oracle/log ... osi/trace/osi_ora_6825.trc
    Active Problem Count  0
    Active Incident Count 0
    

    告警日志

    每个数据库都有一个告警日志,它是一个 XML 文件,其中包含了数据库消息和错误的时间日志。

    告警日志包含以下内容:

    • 所有内部错误(ORA-600),块损坏错误(ORA-1578)以及死锁错误(ORA-60)
    • 数据库管理操作,例如 SQL*Plus 的 STARTUP、
      SHUTDOWN、ARCHIVE LOG 以及 RECOVER 命令
    • 与共享服务器和调度进程功能相关的一些消息和错误
    • 物化视图自动刷新错误

    Oracle 数据库使用告警日志作为在 Enterprise Manager GUI 中显示信息的替代方案。如果成功执行一个管理操作,Oracle 数据库将会在告警日志中写入一个带时间戳的“已完成”的消息。

    首次启动一个实例时,Oracle 数据库在图 13-8 所示的 alert 子目录中创建一个告警日志文件,即使还没有创建数据库。该文件使用 XML 格式。在 trace 子目录中存在一个纯文本的告警日志,以下是某个告警日志的一部分:

    Fri Nov 02 12:41:58 2014
    SMP system found. enable_NUMA_support disabled (FALSE)
    Starting ORACLE instance (normal)
    CLI notifier numLatches:3 maxDescs:189
    LICENSE_MAX_SESSION = 0
    LICENSE_SESSIONS_WARNING = 0
    Initial number of CPU is 2
    Number of processor cores in the system is 2
    Number of processor sockets in the system is 2
    Shared memory segment for instance monitoring created
    Picked latch-free SCN scheme 3
    Using LOG_ARCHIVE_DEST_1 parameter default value as /disk1/oracle/dbs/arch
    Autotune of undo retention is turned on.
    IMODE=BR
    ILAT =10
    LICENSE_MAX_USERS = 0
    SYS auditing is disabled
    NOTE: remote asm mode is local (mode 0x1; from cluster type)
    Starting up:
    Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
    With the Partitioning, Advanced Analytics and Real Application Testing options.
    .
    .
    .
    Using parameter settings in client-side pfile 
    System parameters with nondefault values:
      processes                = 100
      sessions                 = 172
    

    正如示例 13-1所示,可以查询 V$DIAG_INFO 找到告警日志文件的位置。

    DDL 日志

    DDL 日志(DDL log)的格式及基本特性和告警日志相同,但是只包含了 DDL 语句和相关细节信息。数据库将 DDL 的信息写入单独的文件,以便减少告警日志的复杂性。

    DDL 日志记录 DDL 文本,或者一些额外的信息。每个 DDL 语句记录一条日志。DDL 存储在 ADR 主目录下的 log/ddl 子目录中。

    跟踪文件

    跟踪文件(trace file)存储了用于调查问题的诊断数据。同时,跟踪文件还可以为应用程序或实例优化的提供指导。

    跟踪文件的类型

    每个服务器进程或后台进程都可以定期写入一个关联的跟踪文件。该文件中包含了进程环境、状态、活动以及错误的信息。

    SQL 跟踪工具也可以创建跟踪文件,为特定 SQL 语句提供性能相关的信息。可以以不同的方式为指定客户端标识、服务、模块、操作、会话、实例或者数据库启用跟踪。例如,可以通过执行 DBMS_MONITOR 包中的相应过程或者设置事件的方式启动跟踪。

    跟踪文件的位置

    ADR 在 trace 子目录中存储跟踪文件。跟踪文件名称取决于不同的系统,并且使用 .trc 扩展名。

    通常来说数据库后台进程的跟踪文件名称包含 Oracle SID、后台进程名以及操作系统进程编号。mytest_reco_10355.trc 是 一个 RECO 进程跟踪文件的示例。

    服务器进程的跟踪文件名称包含 Oracle SID、字符串“ora”以及操作系统进程编号。mytest_ora_10304.trc 是一个服务器进程跟踪文件的示例。

    有时候跟踪文件还拥有一个跟踪元数据文件,使用扩展名 .trm。这些文件中包含了称为跟踪映射(trace maps)的结构信息,数据库利用这些信息进行搜索和导航。

    跟踪文件的拆分

    如果设置了跟踪文件的大小限制,数据库自动将其拆分成最多五个分段。每个分段都是独立的文件,名称和活动的跟踪文件一致,只是加上了一个编号,例如 ora_1234_2.trc。

    每个分段通常是 MAX_DUMP_FILE_SIZE 参数的 20% 大小。每当所有分段的总大小超过了限制,数据库将会删除最早的分段(永远不会删除第一个分段,因为它包含了进程初始状态的相关信息),然后创建一个新的空分段文件。

    诊断转储文件

    诊断转储文件(diagnostic dump file)是一种特殊的跟踪文件,包含了关于某个状态或结构的详细时间点信息。

    跟踪往往是连续的诊断数据。与此相反,转储通常是针对某一事件的一次性诊断数据。

    跟踪转储与事件

    大多数跟踪转储由事件触发。

    当一个事件发生时,数据库在该事件的事件目录中写入一个或多个转储文件。事件转储文件的名称中还包含了事件编号。

    创建事件时,应用可能会为某个操作产生一个堆转储或者系统状态转储。这种情况下,数据库将转储名称添加到事件文件名之后,而不是默认的跟踪文件名之后。例如,由于一个进程的产生事件时,数据库创建 prod_ora_90348.trc 文件。该事件的转储操作产生 prod_ora_90348_incident_id.trc 文件,其中 incident_id 是该事件的数字 ID。随着该事件创建的堆转储操作产生一个堆转储文件 prod_ora_90348_incident_id_dump_id.trc,其中 dump_id 是跟踪转储的数字 ID。

    展开全文
  • Java corba 实例

    千次阅读 2015-01-23 12:03:27
     CORBA(Common Object Request Broker Architecture,公共对象请求代理体系结构,通用对象请求代理体系结构)是由OMG组织制订的一种标准的面向对象应用程序体系规范。或者说 CORBA体系结构是对象管理组织(OMG)为...

           .NET 和 Java 在技术布局上非常类似,.NET 的远程调用经历了DCOM,.NET Remoting,最后是几乎成了.NET 平台SOA代名词的WCF.WCF的目标在于通过一种通用简单的协议来实现通信,即SOAP。WebService的理念的兴起给远程调用,分布式系统的设计带来了很多新的思想。在互联网出现之后,REST 的架构模式下,.NET 上有ASP.NET WebApi ,使用比WCF更为轻量级的Http协议。Java 这方面,WebService 和 Corba 的争议由来已久。比如,http://www.docin.com/p-482871623.htmlhttp://blog.csdn.net/liuxuezong/article/details/7661641,也有人提出将二者进行融合,各取所长。

           CORBA(Common Object Request Broker Architecture,公共对象请求代理体系结构,通用对象请求代理体系结构)是由OMG组织制订的一种标准的面向对象应用程序体系规范。或者说 CORBA体系结构是对象管理组织(OMG)为解决分布式处理环境(DCE)中,硬件和软件系统的互连而提出的一种解决方案;OMG组织是一个国际性的非盈利组织,其职责是为应用开发提供一个公共框架,制订工业指南和对象管理规范,加快对象技术的发展。
          使用CORBA,用户可以透明地访问信息,并不需要知道信息存在于什么软件中、使用什么硬件平台,以及位于企业网络的什么地方。作为面向对象系统的通信核心,CORBA为今天的计算环境带来了真正的互操作性。 
           CORBA与JAVA的相互关系 
      CORBA不只意味着对象请求代理(ORB),它还是非常全面的分布式对象平台。CORBA使JAVA应用可以跨越网络、语言以及操作系统,并为JAVA提供了一组分布服务,如分布式自我观察、动态发现、事务、关系、安全和命名等。 
           JAVA不仅是一种语言,它还是一个动态代码系统,它对运行对象来说是一个可移植的虚拟机(JVM)。JAVA为开发、管理、发布Client/Server应用提供了更简单的方式。人们可以通过将应用放在一个Web服务器上将这一应用发布给成千上万个用户,而不必关心它的安装和升级。JAVA还非常适合服务器的开发,它可以动态地将服务代码移向最需要它们的地方。 
           JAVA将会使CORBA对象能够运行在从主机、网络计算机到蜂窝电话等可编程的各种机器上,并简化了大型CORBA系统的代码发布。对客户和服务对象来说JAVA是很理想的编程语言,JAVA内置的多线程、垃圾收集和错误处理使编写健壮的网络对象变得很容易。 
            这两种对象模型可以很好地相互补充,CORBA处理网络的透明性,JAVA处理实现的透明性,CORBA为JAVA可移植应用环境提供了一个分布式的结构。

           下面有一个Corba例子。

           1. 搭建项目框架

           新建两个项目MyCorbaServer和MyCorbaClient.结构如下:

     

    2.使用idl定义接口

    idl 是接口定义语言,关于idl的语法,上一篇已经介绍了。http://blog.csdn.net/afandaafandaafanda/article/details/43027253

    module CorbaAlgorithm{
       typedef double d;
       interface Algorithm{
          string GetName();
          d Add(in d x,in d y);
          d Sub(in d x,in d y);
          d Mul(in d x,in d y);
          d Div(in d x,in d y);
       };
    };

    接口里面涉及了自定义的类型,注意参数要使用in

    接下来使用idlj 生成CorbaAlgorithm文件夹下的文件。

    idlj -fall Algorithm.idl

    如果运行正确会生成下列文件

    3.在服务端实现接口

    package AlgorithmServer;
    
    import CorbaAlgorithm.AlgorithmPOA;
    
    public class AlgorithmImpl extends AlgorithmPOA {
    
    	@Override
    	public String GetName() {
    		// TODO Auto-generated method stub
    		return "Corba is good";
    	}
    
    	@Override
    	public double Add(double x, double y) {
    		// TODO Auto-generated method stub
    		return x + y;
    	}
    
    	@Override
    	public double Sub(double x, double y) {
    		// TODO Auto-generated method stub
    		return x - y;
    	}
    
    	@Override
    	public double Mul(double x, double y) {
    		// TODO Auto-generated method stub
    		return x*y;
    	}
    
    	@Override
    	public double Div(double x, double y) {
    		// TODO Auto-generated method stub
    		try
    		{
    			return x / y;
    		}catch(Exception ex)
    		{
    			ex.printStackTrace();
    			return -100000;
    		}
    	}
    }
    


    4. 在服务端发布

    package AlgorithmServer;
    
    import org.omg.CORBA.ORB;
    import org.omg.CosNaming.NameComponent;
    import org.omg.CosNaming.NamingContextExt;
    import org.omg.CosNaming.NamingContextExtHelper;
    import org.omg.PortableServer.POA;
    import org.omg.PortableServer.POAHelper;
    
    import AlgorithmServer.AlgorithmImpl;
    import CorbaAlgorithm.Algorithm;
    import CorbaAlgorithm.AlgorithmHelper;
    
    public class AlgorithmServer {
    	
    	public static void main(String[] args) throws Exception {
    		// TODO Auto-generated method stub
    		args = new String[2];
    		args[0] = "-ORBInitialPort";
    		args[1] = "1050";//端口
    		ORB orb = ORB.init(args, null);
    		System.out.println("server--->01 ORB init started.");
    		
    		org.omg.CORBA.Object obj=orb.resolve_initial_references("RootPOA");
    		POA rootpoa = POAHelper.narrow(obj);
    		rootpoa.the_POAManager().activate();
    		System.out.println("server--->02 POA has been actived.");
    
    		// AlgorithmImpl
    		AlgorithmImpl algorithmImpl = new AlgorithmImpl();
    		System.out.println("server--->03 AlgorithmImpl has been created.");
    
    		// 从服务中得到对象的引用
    		org.omg.CORBA.Object ref = rootpoa.servant_to_reference(algorithmImpl);
    		Algorithm href = AlgorithmHelper.narrow(ref);
    		System.out.println("server--->04 narrow");
    		
    		// 得到一个根名称的上下文
    		org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
    		NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
    		System.out.println("server--->05 Get context by root name.");
    
    		// 在命名上下文中绑定这个对象
    		String name = "Algorithm";
    		NameComponent path[] = ncRef.to_name(name);
    		ncRef.rebind(path, href);
    		System.out.println("server--->06 object binded.");
    
    		// 启动线程服务,等待客户端调用
    		orb.run();
    	}
    
    }
    


    5.在客户端调用

    import org.omg.CORBA.ORB;
    import org.omg.CORBA.ORBPackage.InvalidName;
    import org.omg.CosNaming.NamingContextExt;
    import org.omg.CosNaming.NamingContextExtHelper;
    import org.omg.CosNaming.NamingContextPackage.CannotProceed;
    import org.omg.CosNaming.NamingContextPackage.NotFound;
    
    import CorbaAlgorithm.Algorithm;
    import CorbaAlgorithm.AlgorithmHelper;
    
    public class AlgorithmClient {
    
    	static Algorithm helloImpl;
    
    	static {
    		System.out.println("Client init config stated!-" + System.currentTimeMillis());
    
    		// -ORBInitialHost 127.0.0.1 -ORBInitialPort 1050
    		String args[] = new String[4];
    		args[0] = "-ORBInitialHost";
    		args[1] = "127.0.0.1";// 服务端的IP地址
    		args[2] = "-ORBInitialPort";
    		args[3] = "1050";// 服务端的端口
    
    		// 创建一个ORB实例
    		ORB orb = ORB.init(args, null);
    
    		// 获取根名称上下文
    		org.omg.CORBA.Object objRef = null;
    		try {
    			objRef = orb.resolve_initial_references("NameService");
    		} catch (InvalidName e) {
    			e.printStackTrace();
    		}
    		NamingContextExt neRef = NamingContextExtHelper.narrow(objRef);
    
    		String name = "Algorithm";
    		try {
    			helloImpl = AlgorithmHelper.narrow(neRef.resolve_str(name));
    		} catch (NotFound e) {
    			e.printStackTrace();
    		} catch (CannotProceed e) {
    			e.printStackTrace();
    		} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
    			e.printStackTrace();
    		}
    
    		System.out.println("Client init config ended!" + System.currentTimeMillis());
    	}
    	
    	public static void main(String args[]) throws Exception {
    		sayHello();
    	}
    
    	public static void sayHello() {
    		System.out.println(helloImpl.GetName());
    		System.out.println(helloImpl.Add(3.0,4.5));
    		System.out.println(helloImpl.Sub(3.0,4.5));
    		System.out.println(helloImpl.Mul(3.0,4.5));
    		System.out.println(helloImpl.Div(3.0,4.5));
    	}
    
    }
    

    6.启动程序

    运行server输出如下信息:

    server--->01 ORB init started.
    server--->02 POA has been actived.
    server--->03 AlgorithmImpl has been created.
    server--->04 narrow
    server--->05 Get context by root name.
    server--->06 object binded.


    运行client输出如下信息:

    Client init config stated!-1421987422309
    Client init config ended!1421987422571
    Corba is good
    7.5
    -1.5
    13.5
    0.6666666666666666
    


    我们看到我们定义的接口顺利调用了!


     

     

          

    展开全文
  • 接下来我分享“组织机构管理”模块主要的核心代码组织机构管理使用的EasyUI控件,主要是EasyUI的TreeGrid控件组织机构管理模块提供直观方便的组织机构管理,以树型结构显示单位和部门的机构体系,可根据需要进行添加...

    使用Jquery+EasyUI 进行框架项目开发案例讲解之四

    组织机构管理源码分享 

        在上三篇文章

       《使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享》 

      《使用Jquery+EasyUI 进行框架项目开发案例讲解之二---用户管理源码分享》

      《使用Jquery+EasyUI 进行框架项目开发案例讲解之三---角色管理源码分享》

      我们分享了使用Jquery EasyUI来进行ASP.NET项目的开发的相关方法,每一个模块都有其共用性,细细理解与掌握,我相信使用EasyUI进行开发还是相当方便的。

      接下来我分享“组织机构管理”模块主要的核心代码组织机构管理使用的EasyUI控件,主要是EasyUI的TreeGrid控件,组织机构管理主界面如下图所示:

      

      在进行代码讲解之前,我们先来回顾一个TreeGrid相关的知识。easyUI TreeGrid 从$.fn.datagrid.defaults继承,覆盖默认值$.fn.treegrid.defaults。treegrid 是使用显示分层数据在grid中,treegrid 是基于datagrid和关联treeview 和关联可编辑的grid,treegrid 允许你创建定制的,异步加载展开行数据,和显示分层的数据在多列中。如下图所示:

      

      使用示例

      通过html标记创建treegrid ,大多数情况下treegrid 遵循相同的结构格式化为datagrid
    <table id="tt" class="easyui-treegrid" style="width:600px;height:400px"  
            data-options="url:'get_data.aspx',idField:'id',treeField:'name'">  
        <thead>  
            <tr>  
                <th data-options="field:'name',width:180">Task Name</th>  
                <th data-options="field:'persons',width:60,align:'right'">Persons</th>  
                <th data-options="field:'begin',width:80">Begin Date</th>  
                <th data-options="field:'end',width:80">End Date</th>  
            </tr>  
        </thead>  
    </table> 

    使用javascript创建treegrid 

    <table id="tt" style="width:600px;height:400px"></table>  

    $('#tt').treegrid({  
        url:'get_data.aspx',  
        idField:'id',  
        treeField:'name',  
        columns:[[  
            {title:'Task Name',field:'name',width:180},  
            {field:'persons',title:'Persons',width:60,align:'right'},  
            {field:'begin',title:'Begin Date',width:80},  
            {field:'end',title:'End Date',width:80}  
        ]]  
    }); 

    属性

      属性从 datagrid继承,以下是treegrid新增的属性.

    NameTypeDescriptionDefault
    idFieldstring定义键字段标识一个tree节点,该项是必须的.null
    treeFieldstring定义tree节点字段,该项是必须的.null
    animateboolean定义当节点展开/关闭的时候,是否显示动画效果.false
    loaderfunction(param,success,error)定义如何从远程服务器端加载数据. 返回false将终止这个动作. 这个函数提供一下参数 :
    param: 传递给远程服务器的参数对象.
    success(data): 当检索数据成功之后执行的回调函数.
    error(): 当检索数据失败的时候调用的回调函数.
    json loader
    loadFilterfunction(data,parentId)返回过滤后的显示数据. 

     

      事件

      事件从datagrid继承, 以下是datagrid新增事件.

    NameParametersDescription
    onClickRowrow当用户点击一个节点时触发.
    onDblClickRowrow当用户双击一个节点时触发.
    onClickCellfield,row当用户点击一个表格的时触发.
    onDblClickCellfield,row当用户双击一个表格的时触发.
    onBeforeLoadrow, param一个请求去加载数据之前触发, 返回false将取消加载动作.
    onLoadSuccessrow, data数据加载成功之后触发.
    onLoadErrorarguments数据加载失败之后触发,arguments 参数和jQuery.ajax的error函数一样.
    onBeforeExpandrow节点展开之前触发,返回false将取消展开动作.
    onExpandrow节点展开后触发.
    onBeforeCollapserow节点折叠之前触发,返回false取消折叠动作.
    onCollapserow节点折叠后触发.
    onContextMenue, row在节点上右键点击触发.
    onBeforeEditrow用户开始编辑一个节点时触发.
    onAfterEditrow,changes用户结束编辑节点时触发.
    onCancelEditrow用户取消编辑节点时触发.

       方法  

      许多方法提供一个参数,参数名为id, 这个参数指明tree节点值.

    NameParameterDescription
    optionsnone返回treegrid的 options对象.
    resizeoptions设置treegrid 大小,options包含两个属性:
    width: treegrid新的宽度.
    height: treegrid新的高度.
    fixRowHeightid固定特定行高度.
    loadDatadata加载 treegrid 数据.
    reloadid重新加载treegrid 数据.如果传递了id参数, 重新加载特定的tree行, 其他的重新加载所有tree行.

    示例代码:

    $('#tt').treegrid('reload', 2);	// 重新加载指定id值是2的行
    $('#tt').treegrid('reload');	// 重新加载所有行
    
    reloadFooterfooter重新加载页脚数据.
    getDatanone得到加载数据.
    getFooterRowsnone得到页脚数据.
    getRootnone得到根节点, 返回的是节点对象
    getRootsnone得到根节点, 返回的是节点数组.
    getParentid得到父节点.
    getChildrenid得到子节点.
    getSelectednone得到选中节点并返回它, 如果没有选中节点返回null.
    getSelectionsnone得到所有的选中节点.
    getLevelid得到特定的节点的层级.
    findid查找特定的节点和返回节点数据.
    selectid选中一个节点.
    unselectid取消选中一个节点.
    selectAllnone选中所有节点.
    unselectAllnone取消选中所有节点.
    collapseid折叠一个节点.
    expandid展开一个节点.
    collapseAllid折叠所有节点.
    expandAllid展开所有节点.
    expandToid展开从根节点到指定的节点.
    toggleid切换节点的 expanded(展开)/collapsed (关闭)状态.
    appendparam附加一个节点到父节点. 'param' 参数包含以下属性:
    parent:父节点id , 如果没有分配, 附加作为根节点.
    data: 数组, 节点数据.
    示例代码:
    // 添加一些节点到选中节点
    var node = $('#tt').treegrid('getSelected');
    $('#tt').treegrid('append',{
    	parent: node.id,  // 节点有一个'id'值,定义是通过'idField'属性
    	data: [{
    		id: '073',
    		name: 'name73'
    	}]
    });
    
    removeid移除一个节点和其子节点.
    refreshid刷新特定的节点.
    beginEditid开始编辑一个节点.
    endEditid结束编辑一个节点.
    cancelEditid取消编辑一个节点.
    getEditorsid得到特定行编辑器.每一个编辑器都有以下属性:
    actions:编辑器可以做的动作.
    target: 目标编辑器jQuery对象.
    field:字段名.
    type:编辑器类型.
    getEditoroptions得到特定的编辑器, options 包含两个属性:
    id:行节点id.
    field: 字段名.

     

      以上知识对于充分理解并应用TreeGrid非常的重要,对于不明白的童鞋可以看下!下面分享如何使用EasyUI的TreeGrid控件进行我们的组织机构管理的开发,当然还涉及到其他的知识点,在前面的文章已有介绍,不明白的可以看下前面的文章,这儿重在说明一些方法,当然大家也可交流讨论,提出你们在开发过程中使用的常用方式方法。

      一、“组织机构管理”主界面UI的ASPX代码如下:

    <%@ Page Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="OrganizeAdmin.aspx.cs" Inherits="RDIFramework.WebApp.Modules.OrganizeAdmin" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">      
         <div id="toolbar">
            <%=base.BuildToolBarButtons()%>
        </div>
        <table id="organizeGrid"></table> 
        <script type="text/javascript" src="../Scripts/Business/OrganizeAdmin.js?v=5"></script>   
    
    </asp:Content>

      可以看到,代码非常的简洁,使用EasyUI开发的好处就在于此,不需要你拖动服务端的控件等这种常规的Asp.NET开发方式,对于这种开发方式的好处不言而喻。

      绑定当前登录用户所拥有的功能按钮列表代码如下: 

     	/// <summary>
            /// 获得页面的权限
            /// </summary>
            private void GetPermission()
            {
                this.permissionAdd = this.IsAuthorized("OrganizeManagement.Add");
                this.permissionEdit = this.IsAuthorized("OrganizeManagement.Edit");
                this.permissionMove = this.IsAuthorized("OrganizeManagement.Move");
                this.permissionDelete = this.IsAuthorized("OrganizeManagement.Delete");
                this.permissionExport = this.IsAuthorized("OrganizeManagement.Export");
                //this.permissionAccredit = this.IsAuthorized("UserManagement.Accredit");
                this.permissionUserOrganizePermission = this.IsAuthorized("OrganizeManagement.UserOrganizePermission");
                this.permissionRolerOrganizePermission = this.IsAuthorized("OrganizeManagement.RolerOrganizePermission");
            }
    
            /// <summary>
            /// 加载工具栏
            /// </summary>
            /// <returns>工具栏HTML</returns>
            public override string BuildToolBarButtons()
            {
                StringBuilder sb = new StringBuilder();
                string linkbtn_template = "<a id=\"btn{0}\" class=\"easyui-linkbutton\" style=\"float:left\"  plain=\"true\" href=\"javascript:;\" icon=\"{1}\"  {2} title=\"{3}\">{4}</a>";
                sb.Append("<a id=\"a_refresh\" class=\"easyui-linkbutton\" style=\"float:left\"  plain=\"true\" href=\"javascript:;\" icon=\"icon-reload\"  title=\"重新加载\">刷新</a> ");
                sb.Append("<div class='datagrid-btn-separator'></div> ");
                sb.Append(string.Format(linkbtn_template, "Add", "icon-add", permissionAdd ? "" : "disabled=\"True\"", "新增组织机构", "新增"));
                sb.Append(string.Format(linkbtn_template, "Edit", "icon-edit", permissionEdit ? "" : "disabled=\"True\"", "修改选中的组织机构", "修改"));                      
                sb.Append(string.Format(linkbtn_template, "Delete", "icon-delete0", permissionDelete ? "" : "disabled=\"True\"", "删除选中组织机构", "删除"));
                sb.Append("<div class='datagrid-btn-separator'></div> ");
                sb.Append(string.Format(linkbtn_template, "MoveTo", "icon-shape_move_forwards", permissionMove ? "" : "disabled=\"True\"", "移动选中的组织机构", "移动"));
                sb.Append(string.Format(linkbtn_template, "Export", "icon-export", permissionExport ? "" : "disabled=\"True\"", "导出组织机构数据", "导出"));
                sb.Append("<div class='datagrid-btn-separator'></div> ");
                sb.Append(string.Format(linkbtn_template, "UserOrganizePermission", "icon-layout_key", permissionUserOrganizePermission ? "" : "disabled=\"True\"", "设置用户组织机构权限", "用户组织机构权限"));
                sb.Append(string.Format(linkbtn_template, "RoleOrganizePermission", "icon-ruby_key", permissionRolerOrganizePermission ? "" : "disabled=\"True\"", "设置角色组织机构权限", "角色组织机构权限"));
                return sb.ToString();
            }

     绑定TreeGridJS代码如下:  

    $(function () {
        autoResize({ dataGrid: '#organizeGrid', gridType: 'treegrid', callback: mygrid.bindGrid, height: 5 });
        $('#btnAdd').click(OrganizeAdminMethod.AddOrganize); //新增组织机构
        $('#btnEdit').click(OrganizeAdminMethod.EditOrganize); //修改组织机构
        $('#btnDelete').click(OrganizeAdminMethod.DeleteOrganize); //删除组织机构
        $('#btnMoveTo').click(OrganizeAdminMethod.MoveTo); //移动组织机构
        $('#btnExport').click(OrganizeAdminMethod.ExportOrganize); //导出组织机构数据
        $('#btnUserOrganizePermission').click(OrganizeAdminMethod.SetUserOrganizePermission); //设置用户组织机构权限
        $('#btnRoleOrganizePermission').click(OrganizeAdminMethod.SetRoleOrganizePermission); //设置角色组织机构权限
        $('#a_refresh').click(function () { //刷新
            mygrid.reload();
        });
    });
    
    var mygrid = {
        bindGrid: function (winsize) {       
            navgrid = $('#organizeGrid').treegrid({
                toolbar: '#toolbar',
                title: '组织机构列表',
                iconCls: 'icon icon-org',
                width: winsize.width,
                height: winsize.height,            
                nowrap: true,
                rownumbers: true,
                animate: true,
                resizable: true,
                collapsible: false,
                url: actionUrl,
                idField: 'Id',
                treeField: 'FullName',
                frozenColumns: [[
                    { title: '组织机构名称', field: 'FullName', width: 200 },
                    { title: '编码', field: 'Code', width: 100 }
                ]],
                columns: [[
                    { title: '简称', field: 'ShortName', width: 120 },                      
                    { title: '主负责人', field: 'Manager', width: 70, align: 'center' },
                    { title: '电话', field: 'OuterPhone', width: 100, align: 'center' },
                    { title: '传真', field: 'Fax', width: 100, align: 'center' },
                    { title: '有效', field: 'Enabled', width: 50, align: 'center', formatter: imgcheckbox },
                    { title: '排序', field: 'SortCode', width: 80, align: 'center' },
                    { title: '备注', field: 'Description', width: 300 },
                    { title: 'ParentId', field: 'ParentId', hidden: true },
                    { title: 'Category', field: 'Category', hidden: true },
                    { title: 'InnerPhone', field: 'InnerPhone', hidden: true },
                    { title: 'Postalcode', field: 'Postalcode', hidden: true },
                    { title: 'Address', field: 'Address', hidden: true },
                    { title: 'Web', field: 'Web', hidden: true },
                    { title: 'AssistantManager', field: 'AssistantManager', hidden: true },
                    { title: 'IsInnerOrganize', field: 'IsInnerOrganize', hidden: true }
                ]]
            });
        },
        reload: function () {
            navgrid.treegrid('reload');
        },
        selected: function () {
            return navgrid.treegrid('getSelected');
        }
    }
    
    var imgcheckbox = function (cellvalue, options, rowObject) {
        return cellvalue ? '<img src="/css/icon/ok.png" alt="正常" title="正常" />' : '<img src="/css/icon/stop.png" alt="禁用" title="禁用" />';
    }

      添加组织机构界面窗口如下: 

      

      在添加组织机构界面,主负责人,副主管数据域的绑定控件使用的是“ComboGrid"控件,绑定的代码如下:

    bindComboGrid: function () {
            top.$('#txt_Manager,#txt_AssistantManager').combogrid({
                panelWidth: 320,
                idField: 'Id',
                textField: 'RealName',
                url: 'Modules/handler/UserAdminHandler.ashx?action=GetUserListByPage',
                sortName: 'SortCode',
                sortOrder: 'asc',
                fitColumns: true,
                showPageList: false,
                striped: true,
                pagination: true,
                rownumbers: true,
                fitColumns: true,
                pageSize: 10,
                pageList: [10, 20, 30, 50],
                method: 'post',
                columns: [[
                    { title: '登录名', field: 'UserName', width: 60, sortable: true },
                    { title: '用户名', field: 'RealName', width: 70 }
                ]]
            });

    修改组织机构界面如下: 

      

      ”修改组织机构“代码如下: 

    EditOrganize: function () { //修改组织机构
            if ($(this).linkbutton('options').disabled == true) {
                return;
            }
            //功能代码逻辑...
            var row = mygrid.selected();
            if (row) {
                var editDailog = top.$.hDialog({
                    href: formUrl, title: '修改组织机构', iconCls: 'icon-edit', width: 750, height: 520,
                    onLoad: function () {
                        pubMethod.bindCtrl(row.Id);
                        pubMethod.bindCategory();
                        pubMethod.bindComboGrid();
                        top.$('#txt_Code').val(row.Code);
                        top.$('#txt_FullName').val(row.FullName);
                        top.$('#txt_ShortName').val(row.ShortName);
                        top.$('#txt_ParentId').combotree('setValue', row.ParentId);
                        top.$('#txt_Category').combobox('setValue', row.Category);
                        top.$('#txt_Manager').combogrid('setValue', row.Manager);
                        top.$('#txt_AssistantManager').combogrid('setValue', row.AssistantManager);
                        top.$('#txt_OuterPhone').val(row.OuterPhone);
                        top.$('#txt_InnerPhone').val(row.InnerPhone);
                        top.$('#txt_Fax').val(row.Fax);
                        top.$('#txt_Postalcode').val(row.Postalcode);
                        top.$('#txt_Web').val(row.Web);
                        top.$('#txt_Address').val(row.Address);
                        top.$('#chk_Enabled').attr('checked', row.Enabled == "1");
                        top.$('#chk_IsInnerOrganize').attr('checked', row.IsInnerOrganize == "1");
                        top.$('#txt_Description').val(row.Description);
                    },
                    submit: function () {
                        if (top.$('#uiform').validate().form()) {
                            
                            //保存时判断当前节点所选的父节点,不能为当前节点的子节点,这样就乱套了....
                            var treeParentId = top.$('#txt_ParentId').combotree('tree'); // 得到树对象
                            var node = treeParentId.tree('getSelected');
                            if (node) {                            
                                var nodeParentId = treeParentId.tree('find', row.Id);
                                var children = treeParentId.tree('getChildren', nodeParentId.target);
                                var nodeIds = '';
                                var isFind = 'false';
                                for (var index = 0; index < children.length; index++) {
                                    if (children[index].id == node.id) {
                                        isFind = 'true';
                                        break;
                                    }
                                }
    
                                if (isFind == 'true') {
                                    top.$.messager.alert('温馨提示', '请选择父节点元素!', 'warning');
                                    return;
                                }
                            }
    
    
                            var vparentid = top.$('#txt_ParentId').combobox('getValue');
                            var vcategory = top.$('#txt_Category').combobox('getValue');
                            var vmanager = top.$('#txt_Manager').combogrid('getText');
                            var vassistantmanager = top.$('#txt_AssistantManager').combogrid('getText');
                            var query = 'action=EditOrganize&vparentid=' + vparentid + '&vcategory=' + vcategory + '&KeyId=' + row.Id + '&vmanager=' + vmanager + '&vassistantmanager=' + vassistantmanager + '&'
                                      + top.$('#uiform').serialize();
                            $.ajaxjson(actionUrl, query, function (d) {
                                if (d.Success) {
                                    msg.ok(d.Message);
                                    editDailog.dialog('close');
                                    mygrid.reload();
                                } else {
                                    MessageOrRedirect(d);
                                }
                            });
                        }
                    }
                });
    
    
            } else {
                msg.warning('请选择要修改的组织机构!');
                return false;
            }
            return false;
        }

    删除组织机构代码如下:  

    DeleteOrganize: function () { //删除组织机构
            if ($(this).linkbutton('options').disabled == true) {
                return;
            }
            //功能代码逻辑...
            var row = mygrid.selected();
            if (row != null) {
                var childs = $('#organizeGrid').treegrid('getChildren', row.Id);
                if (childs.length > 0) {
                    $.messager.alert('警告提示', '当前所选有子节点数据,不能删除。', 'warning');
                    return false;
                }
                var query = 'action=DeleteOrganize&KeyId=' + row.Id;
                $.messager.confirm('询问提示', '确认要删除选中的组织机构吗?', function (data) {
                    if (data) {
                        $.ajaxjson(actionUrl, query, function (d) {
                            if (d.Success) {
                                msg.ok(d.Message);
                                mygrid.reload();
                            } else {
                                MessageOrRedirect(d);
                            }
                        });
                    }
                    else {
                        return false;
                    }
                });
            }
            else {
                msg.warning('请选择要删除的组织机构!');
                return false;
            }
            return false;
        }

     “用户-组织机构权限设置”功能主要用于设置特定用户可以访问的组织机构。有时我们会有这样的应用,某些数据属于某个组织机构内部的数据,只能指定其他组织机构特定的用户访问,那么通过此设置,我们就可以轻松的控制特定的用户访问指定的组织机构,“用户-组织机构权限设置”如下图所示。

      

      在上图中,我们可以看到对用户“陈俊熙”设置了他可以访问的组织机构,我们现在以他的用户“wikstone”登录系统,可以看到当前用户只能看到对应的组织机构了,如下图所示:

      

      用户-组织机构权限设置代码如下:  

    SetUserOrganizePermission: function () { //设置用户组织机构权限
            if ($(this).linkbutton('options').disabled == true) {
                return;
            }
            //功能代码逻辑...
            var userGrid;
            var curResourceTargetResourceIds = [];
            var setDialog = top.$.hDialog({
                title: '(用户-组织机构)权限设置',
                width: 670, height: 600, iconCls: 'icon-layout_key', //cache: false,
                href: "Modules/html/PermissionBacthSetForm.htm?n=" + Math.random(),
                onLoad: function () {
                    using('panel', function () {
                        top.$('#panelTarget').panel({ title: '组织机构列表', iconCls: 'icon-org', height: $(window).height() - 3 });
                    });
    
                    userGrid = top.$('#leftnav').datagrid({
                        title: '用户列表',
                        url: 'Modules/handler/UserAdminHandler.ashx',
                        nowrap: false, //折行
                        //fit: true,
                        rownumbers: true, //行号
                        striped: true, //隔行变色
                        idField: 'Id', //主键
                        singleSelect: true, //单选
                        frozenColumns: [[]],
                        columns: [[
                            { title: '登录名', field: 'UserName', width: 120, align: 'left' },
                            { title: '用户名', field: 'RealName', width: 150, align: 'left' }
                        ]],
                        onLoadSuccess: function (data) {
                            top.$('#rightnav').tree({
                                cascadeCheck: false, //联动选中节点
                                checkbox: true,
                                lines: true,
                                url: 'Modules/handler/OrganizeAdminHander.ashx?action=treedata',
                                onSelect: function (node) {
                                    top.$('#rightnav').tree('getChildren', node.target);
                                }
                            });
                            top.$('#leftnav').datagrid('selectRow', 0);
                        },
                        onSelect: function (rowIndex, rowData) {
                            curResourceTargetResourceIds = [];
                            var query = 'action=GetPermissionScopeTargetIds'
                                      + '&resourceCategory=PiUser&resourceId=' + rowData.Id
                                      + '&targetCategory=PiOrganize';
                            $.ajaxtext('handler/PermissionHandler.ashx', query, function (data) {
                                var targetResourceTree = top.$('#rightnav');
                                targetResourceTree.tree('uncheckedAll');
                                if (data == '' || data.toString() == '[object XMLDocument]') {
                                    return;
                                }
                                curResourceTargetResourceIds = data.split(',');
                                for (var i = 0; i < curResourceTargetResourceIds.length; i++) {
                                    var node = targetResourceTree.tree('find', curResourceTargetResourceIds[i]);
                                    if (node)
                                        targetResourceTree.tree("check", node.target);
                                }
                            });
                        }
                    });
                },
                submit: function () {
                    var allSelectTargetResourceIds = permissionMgr.getSelectedResource().split(',');
                    var grantResourceIds = '';
                    var revokeResourceIds = '';
                    var flagRevoke = 0;
                    var flagGrant = 0;
                    while (flagRevoke < curResourceTargetResourceIds.length) {
                        if ($.inArray(curResourceTargetResourceIds[flagRevoke], allSelectTargetResourceIds) == -1) {
                            revokeResourceIds += curResourceTargetResourceIds[flagRevoke] + ','; //得到收回的权限列表
                        }
                        ++flagRevoke;
                    }
    
                    while (flagGrant < allSelectTargetResourceIds.length) {
                        if ($.inArray(allSelectTargetResourceIds[flagGrant], curResourceTargetResourceIds) == -1) {
                            grantResourceIds += allSelectTargetResourceIds[flagGrant] + ','; //得到授予的权限列表
                        }
                        ++flagGrant;
                    }
    
                    var query = 'action=GrantRevokePermissionScopeTargets&resourceId=' + top.$('#leftnav').datagrid('getSelected').Id
                              + '&resourceCategory=PiUser&targetCategory=PiOrganize'
                              + '&grantTargetIds=' + grantResourceIds + "&revokeTargetIds=" + revokeResourceIds;
                    $.ajaxjson('handler/PermissionHandler.ashx', query, function (d) {
                        if (d.Data > 0) {
                            msg.ok('设置成功!');
                        }
                        else {
                            alert(d.Message);
                        }
                    });
                }
            });
    
        }

    “角色-组织机构权限设置”功能与“用户-组织机构权限设置”功能类似,这儿只是做的对角色的控制。(角色-组织机构)权限设置界面如下:。

      

      

    相关资源分享 

    1、基于.NET的快速信息化系统开发整合框架 —RDIFramework.NET—系统目录

    2、Jquery EasyUI官方网站

    3、Jquery学习官方网站

     4、Jquery EasyUI本地实例文件(如果嫌官网速度过慢,可以下载这个看)

    5、Jquery权威指南下载

    6、Jquery权威指南源代码下载

    7、Jquery EasyUI 1.3中文.chm文件下载

    8、JavaScript权威指南(第六版)中文版(强烈推荐)在线观看

     

    作者: EricHu 
    出处:http://blog.csdn.net/chinahuyong  
    Email:406590790@qq.com 
    QQ交流:406590790 
    QQ群:237326100 
    框架博客:http://blog.csdn.net/chinahuyong 
                   http://www.cnblogs.com/huyong
    RDIFramework.NET,基于.NET的快速信息化系统开发、整合框架,给用户和开发者最佳的.Net框架部署方案。 
    关于作者:高级工程师、信息系统项目管理师、DBA。专注于微软平台项目架构、管理和企业解决方案,多年项目开发与管理经验,曾多次组织并开发多个大型项目,在面向对象、面向服务以及数据库领域有一定的造诣。现主要从事基于 RDIFramework.NET 框架的技术开发、咨询工作,主要服务于金融、医疗卫生、铁路、电信、物流、物联网、制造、零售等行业。 
    如有问题或建议,请多多赐教! 
    本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过邮箱或QQ 联系我,非常感谢。

    展开全文
  • 微信公众号开发实例

    万次阅读 2017-08-24 14:06:03
    微信公众号开发实例目录 1.简介 2 1.1 基础知识 2 2.开发准备 5 2.1 业务流程 5 2.2 微信公众号 5 2.3 WEB服务器 8 2.4 通信协议 13 2.5 开发框架 19 2.6 小结 20 3.开发实例 21 3.1 业务流程 21 3.2 ...
  • 区块链应用实例

    万次阅读 2017-11-07 09:44:14
    国家也应该加大投入,一方面动员国有金融机构和科研机构,一方面更多的扶持民营企业和创客、创投,加快区块链底层核心技术和区块链金融应用的良法,争取形成具有我国自由产权的技术成果,同时还应该加快区块链标准...
  • 组织模型是管理软件中系统建模的一个重要组成部分(企业模型一般包括资源模型、组织模型、信息模型、功能模型、流程模型),权限模型是管理软件系统的安全体系的核心,这两个模型本身既有很强的独立性,在具体应用中...
  • 组织机构权限系统的实现(工作流)转自:http://www.cnblogs.com/haore147/p/5213345.html在工作流管理系统中,业务流程的流转,每个节点的办理都是由人或组织共同参与和协作来完成的。工作流管理系统就是业务流程的...
  • 摘自:阿里云RDS通过克隆实例恢复到主实例 阿里云RDS如何通过临时实例恢复到主实例 数据仓库 目前RDS支持数据回滚,回滚是针对整个实例的,不支持单表单库。 临时实例用于对rds进行部分数据的回滚,大致流程是:创建...
  • BPEL实例学习

    千次阅读 2007-03-04 11:30:00
    BPEL 实例教程面向 Web 服务的业务流程执行语言(BPEL 或 BPEL4WS)是一种使用 Web 服务定义和执行业务流程的语言。BPEL 使您可以通过组合、编排和协调 Web 服务自上而下地实现面向服务的体系结构 (SOA)。BPEL 提供...
  • BPEL 实例教程

    千次阅读 2007-03-15 12:03:00
    BPEL 实例教程作者:Matjaz Juric 了解如何创建一个将一系列虚拟的、与旅行相关的 web 服务结合起来的示例业务流程,然后将其部署到 Oracle BPEL Process Manager 运行时环境。
  • 数据仓库常见建模方法与建模实例演示

    万次阅读 多人点赞 2020-04-14 15:52:09
    大数据的数仓建模是通过建模的方法更好的组织、存储数据,以便在 性能、成本、效率和数据质量之间找到最佳平衡点。一般主要从下面四点考虑 访问性能:能够快速查询所需的数据,减少数据I/O 数据成本:减少不必要的...
  • 数据仓库常见建模方法与大数据领域建模实例综述

    千次阅读 多人点赞 2021-05-01 14:01:51
    随着DT时代互联网、智能设备等信息技术的发展,数据开始井喷式的增长,如何讲这些数据进行有序、有结构地分类组织存储是我们面临的一个挑战。 如果把数据看作图书馆里的书,我们希望看到它们在书架上分门别类地放置...
  • 项目管理中的项目组织结构

    千次阅读 2004-12-10 15:17:00
    项目管理中的项目组织结构 作/转载者:刘易勇 一、项目组织基本理论 项目组织是保证工程项目正常实施的组织保证体系,就项目这种一次性任务而言,项目组织建设包括从组织设计、组织运行、组织更 新到组织终结这样一...
  • 机器学习算法应用场景实例

    千次阅读 2020-04-03 17:56:45
    本文整理了60个机器学习算法应用场景实例,含分类算法应用场景20个、回归算法应用场景20个、聚类算法应用场景10个以及关联规则应用场景10个。包含了天池、DataCastle、DataFountain中所有竞赛场景。 目录 1 分类...
  • 实例解析网络钓鱼攻击的幕后

    千次阅读 2019-08-07 17:53:29
    实例解析网络钓鱼攻击的幕后 网络钓鱼是通过大量发送声称来自于银行或其他知名机构的欺骗性垃圾邮件,意图引诱收信人给出敏感信息(如用户名、口令、帐号ID、ATM PIN码或信用卡详细信息)的一种攻击方式。最典型的...
  • C#实例.net_经典例子400个

    万次阅读 多人点赞 2018-07-30 17:04:25
    一共470多例winform 界面特效的源码。 窗体与界面设计...... 实例001 带历史信息的菜单 10 ...实例003 像开始菜单一样漂亮的菜单... 14 实例004 任务栏托盘菜单 15 实例005 可以拉伸的菜单界...
  • wwf票证实例教程

    千次阅读 2010-01-20 17:11:00
    http://download.microsoft.com/download/f/2/7/f279e71e-efb0-4155-873d-5554a0608523/CuttingEdge0603.exe 该实例下载下来后,可能无法运行。当我们运行到wr.StartRuntime();时,他会提示:数据库自动生成的持久...
  • Bug管理系统UML2.0建模实例(一)

    万次阅读 2013-12-16 21:47:28
    实例是Sunny给企业做UML内训时所用教学实例之一,是一个较为完整的UML建模实例,可供大家学习参考之需! 1.项目概述 随着软件项目规模和复杂性的增大,有效跟踪和管理项目中存在的缺陷Bug变得越来越重要。每一...
  • SQL Server 2005 数据库复制实例

    千次阅读 2011-05-12 16:33:00
    SQL Server 2005 数据库同步复制实例
  • C#开发实例大全(提高卷)

    千次阅读 2018-02-26 20:03:00
    下载地址:网盘下载内容简介······《C#开发实例大全(提高卷)》筛选、汇集了C#开发从基础知识到高级应用各个层面约600个实例及源代码,每个实例都按实例说明、关键技术、设计过程、详尽注释、秘笈心法的顺序...
  • 摘要:随着项目管理理念日益深入人心,很多企业已开始建立类似项目管理部、PMO等部门,但在实际运作中由于PMO的定位、公司组织结构、PMO人员自身素质等方面的原因,PMO作用发挥得不尽人意。经过系统培训的PMP常常为...
  • 教你管理SQL实例(1)数据库实例 教你管理SQL实例(2)服务启动帐户 教你管理SQL实例(3)查看启动日志 教你管理SQL实例(4)查看版本号 教你管理SQL实例(5)两大管理利器 教你管理SQL实例(6)服务器排序规则...
  • 为此,国际标准化组织(ISO)在1979年建立了一个 分委员会来专门研究一种用于开放系统互联的体系结构(Open Systems Interconnection)简称OSI,"开放"这个词表示:只要遵循OSI标准,一个系统可以和位于世界上任何...
  • 机器学习算法应用场景实例六十则

    千次阅读 2020-08-18 18:48:46
    本文整理了60个机器学习算法应用场景实例,含分类算法应用场景20个、回归算法应用场景20个、聚类算法应用场景10个以及关联规则应用场景10个。包含了天池、DataCastle、DataFountain中所有竞赛场景。 目录 ...
  • poi3.9导入导出 讲解实例

    千次阅读 2017-06-27 15:07:53
    当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统、银行系统)。或者是:我们已经习惯用Excel打印。这样在我们实际的开发中,很多时候需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,864
精华内容 14,745
关键字:

企业组织结构类型实例