<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>shevliu</title>
    <description></description>
    <link>http://shevliu.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>二、Streams捕获进程</title>
        <author>shevliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shevliu.javaeye.com">shevliu</a>&nbsp;
          链接：<a href="http://shevliu.javaeye.com/blog/190327" style="color:red;">http://shevliu.javaeye.com/blog/190327</a>&nbsp;
          发表时间: 2008年05月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>Streams捕获进程<br /><br />重做日志与捕获进程</strong><br /><br />每个Oracle数据库都包含至少两个重做日志文件，这些文件被共同称为数据库重做日志。重做日志的主要用途是用来记录数据库产生的所有变更。<br />	当人为或硬件原因导致数据出错时，重做日志能确保数据恢复到之前的状态。捕获进程是Oracle的可选后台组件之一，扫描重做日志以捕获对数据库进行的DML和DDL操作，该重做日志所在的数据库称为源数据库。<br /><br /><strong>LCRs（Logical Change Records，逻辑变更记录）</strong><br />捕获进程从重做日志中捕获到变更事件后将其格式化为LCRs。LCR是一种用来描述数据库变更事件的特殊消息，分为两种类型：row LCRs 和 DDL LCRs。<br /><br /><strong>Row LCRs</strong><br /><br />Row LCR 是对库表中单行记录变更的描述信息，一条DML可能同时更新多行记录，所以一条DML可能产生多条Row LCR。而对某一行的LONG,LONG RAW,或是LOB类型字段更新时，同样可能产生多条Row LCR。<br />Row LCR将被包装为LCR$_ROW_RECORD类型，包含以下属性：<br />	source_database_name：源数据库名称。<br />	command_type：产生LCR的DML操作类型，可以是下列类型：INSERT, UPDATE, DELETE, LOB ERASE, LOB WRITE, LOB TRIM。<br />	object_owner: schema名称。<br />	object_name：产生LCR的Table名称。<br />	tag：用以追踪LCR的RAW标签。<br />	transaction_id：运行DML操作的事务标识符。<br />	scn：变更记录写入重做日志时的SCN(system change number)。<br />	old_values：数据更新之前的值。如果DML类型是UPDATE或DELETE，本属性值将是DML操作之前的值，如果DML类型是INSERT，本属性值为空。<br />	new_values：数据更新之后的值。如果DML类型是UPDATE或INSERT，本属性值将是DML操作之后的值，如果DML类型是DELETE，本属性值为空。<br /><br />Row LCR也可包含事务控制语句，例如COMMIT,ROLLBACK。应用过程通过此功能使源数据库与目标数据库保持事务一致性。<br /><br /><strong>DDL LCRs</strong><br /><br />	DDL LCR是对DDL操作的描述信息，DDL通过CREATE,ALTER,DROP等操作改变数据库的结构。<br />	DDL LCR包含以下信息：<br />	source_database_name：源数据库名称。<br />	command_type：产生LCR的DDL操作类型，如ALTER TABLE 或CREATE INDEX。<br />	object_owner：schema名称。<br />	object_name：产生LCR的数据库对象名称。<br />	object_type：产生LCR的数据库对象类型，如TABLE 或 PACKAGE。<br />	ddl_text：DDL语句内容。<br />	logon_user：执行DDL操作的数据库用户。<br />	current_schema：当前使用的schema。<br />	base_table_owner：基础表用户。<br />	base_table_name：基础表名称。<br />	tag：用以追踪LCR的标签。<br />	transaction_id：运行DDL操作的事务标识符。<br />	scn：变更记录写入重做日志时的SCN。<br /><br /><strong>捕获规则</strong><br /><br />	捕获进程根据用户定义的规则对数据库变更进行捕获。我们可以为捕获进程创建正规则集（positive rule set）和负规则集（negative rule set）。<br />	当数据库产生变更时，假如正规则集中的某条规则计算结果为TRUE，捕获进程将截获该条信息；若负规则集中的某条规则计算结果为TRUE，捕获进程将忽略该条信息。若捕获进程同时具有正规则集和负规则集，那么负规则集将优先进行计算。<br /><br /><strong>捕获类型</strong><br /><br />捕获进程能捕获到以下类型字段的变更：<br />_ VARCHAR2<br />_ NVARCHAR2<br />_ NUMBER<br />_ LONG<br />_ DATE<br />_ BINARY_FLOAT<br />_ BINARY_DOUBLE<br />_ TIMESTAMP<br />_ TIMESTAMP WITH TIME ZONE<br />_ TIMESTAMP WITH LOCAL TIME ZONE<br />_ INTERVAL YEAR TO MONTH<br />_ INTERVAL DAY TO SECOND<br />_ RAW<br />_ LONG RAW<br />_ CHAR<br />_ NCHAR<br />_ CLOB<br />_ NCLOB<br />_ BLOB<br />_ UROWID<br /><br />捕获进程不能捕获到以下类型字段的变更：BFILE, ROWID, 用户自定义类型（包括object types,REFs, varrays, nested tables, 以及 Oracle-supplied types），以及经过加密的字段。当捕获进程尝试创建LCR时，若包含加密字段或是不支持的类型，将向用户抛出异常。<br /><br /><strong>实例化Streams环境</strong><br /><br />在单个数据库或是集群环境中，源数据库是指产生消息的数据库，而接收消息的数据库被称为目标数据库。无论是捕获进程已经开始或即将开始捕获数据库变更，还是这些变更即将被本地程序接收或是传递到远程数据库，我们都应该保证这些操作对应的数据库对象已经被实例化。<br />在Streams中，实例化对象有下列步骤：<br />1.	在源数据库中准备好要实例化的对象。<br />2.	如果在目标数据库中没有这些对象的拷贝，则根据源数据库中的对象在目标数据库中创建。我们可以利用export/import, transportable tablespaces, 或者 RMAN来拷贝对象。如果目标数据库中已经有了拷贝，则本步骤省略。<br />3.	在目标数据库中设置实例化SCN（instantiation SCN）。<br /><br />有时，第一步和第三步会由系统自动完成。例如，当我们使用DBMS_STREAMS_ADM包为捕获进程在正规则集中添加规则时，第一步会自动完成。同样，当我们使用export/import 或者 transportable tablespaces将对象从源数据库拷贝到目标数据库时，第三步会自动完成。在apply process从队列中取出消息之前，即使只是将LCR发送给另外的apply handler而非自己进行操作，对象也必须实例化。<br /><br /><strong>本地捕获和远程捕获<br /><br />本地捕获</strong><br /><br />运行在本地源数据库的捕获进程称为本地捕获。配置本地捕获进程时，源数据库将执行以下操作：<br />	运行DBMS_CAPTURE_ADM.BUILD过程以提取或创建重做日志数据字典。<br />	源数据库中的Supplemental logging将附加信息写入重做日志，当apply process对消息进行处理的时候，可能会需要这些信息。<br />	在捕获进程首次运行时，Oracle根据从重做日志中提取出来的数据字典，创建LogMiner数据字典，LogMiner是从主数据字典里分离出来的子集。其他的捕获进程可以共用该LogMiner数据字典，也可以自行创建。<br />	捕获进程通过LogMiner来扫描重做日志。<br />	规则引擎根据规则集中的规则来确定捕获何种数据库变更事件。<br />	捕获进程将满足规则定义的变更截获并放入本地ANYDATA队列中。<br />	若有多个数据库共享该条消息，那么将有多个Propagation将这条消息从源数据库传递到各个目标数据库。<br /><br /><strong>本地捕获的优点</strong><br /><br />本地捕获的优点如下：<br />	配置和管理较为容易。使用本地捕获，不需要将重做日志拷贝到远程数据库，直接在本地进行管理。<br />	本地捕获进程能在数据库变更写入重做日志存档文件（archived redo log file）之前扫描联机日志。如果使用远程捕获，需要在变更写入重做日志存档文件之后将其拷贝到远程数据库，有时甚至需要拷贝重做日志文件（redo log files）。<br />	由于不用将整个重做日志文件拷贝到远程数据库，所以减少了通过网络传递的数据量。即使是在传递已截获的消息时，我们也可以根据传递规则选取必要的消息进行传递。<br />	由于只有本地源数据库能访问重做日志，所以提高了系统安全性。举例来说：假设我们只想捕获schema hr中的变更，只有源数据库有权限扫描重做日志，截获hr中的变更并将其放入队列；但如果使用远程捕获，由于需要拷贝重做日志文件到目标数据库，所以实际上捕获的不仅仅是hr中的变更，而是整个数据库的变更。<br />	如果消息捕获和消息处理都在同一个数据库中，那么配置将会相对简单，查询和计算所需的资源也相对较少。
          <br/>
          <span style="color:red;">
            <a href="http://shevliu.javaeye.com/blog/190327#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 06 May 2008 17:57:12 +0800</pubDate>
        <link>http://shevliu.javaeye.com/blog/190327</link>
        <guid>http://shevliu.javaeye.com/blog/190327</guid>
      </item>
      <item>
        <title>一、Streams概述</title>
        <author>shevliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shevliu.javaeye.com">shevliu</a>&nbsp;
          链接：<a href="http://shevliu.javaeye.com/blog/190189" style="color:red;">http://shevliu.javaeye.com/blog/190189</a>&nbsp;
          发表时间: 2008年05月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>Streams概述</strong><br />	Oracle Streams使信息共享化。每一条共享的信息在Oracle Streams中都被称为一条消息。Stream能在同一个数据库内部或者不同数据库之间传递消息，并且能根据路由配置将指定的消息传递到指定的目的地。它在捕获消息，管理消息，以及在不同数据库或应用程序之间共享消息等方面提供了比传统解决方案更为强大的功能和扩展性,并且提供了分布式企业级应用、数据仓库、高有效性解决方案等功能。我们可以同时使用Oracle Streams提供的所有功能。当需求变更时，我们可以实现新的功能，而不影响现有的功能。<br />	通过Oracle Streams，我们能够掌控诸如：将哪些信息放入stream中，数据库之间消息的流向，消息传递到数据库时做何处理，何时关闭stream等等。根据我们自己制定的规范，Streams能够在数据库中自动的捕获、储存和管理因DML、DDL等操作产生的消息。我们可以向stream中放入自定义的消息，Streams能够自动的将消息传递到其他数据库或者应用程序。根据用户定义的规范，Streams将决定如何处理传递到目的地的消息。<br /><br /><strong>Streams能做什么？</strong><br /><br /><strong>捕获数据库消息</strong><br />      捕获进程（capture process）能够捕获到table、schema、甚至整个数据库的变更。这些变更都会记录到数据库重做日志中，捕获进程从重做日志中捕获到这些变更并将其格式化为LCR（logical change record ， 逻辑变更记录）。哪些消息将被捕获由规则确定，这些消息被称为Captured messages。<br />      产生消息的重做日志所在的数据库被称为源数据库。捕获进程能捕获到本地源数据库或是远程数据库的变更，并将LCR放入相应的队列（Queue），这种方式常被称为隐式捕获。<br />      用户或应用程序可以手动的将LCR或用户自定义的消息放入队列，这种方式常被称为显式捕获。<br /><br /><strong>储存消息到队列</strong><br />	捕获进程将消息放入ANYDATA队列，ANYDATA队列能存放不同类型消息。用户和应用程序同样可以将消息放入ANYDATA队列，也可以放入指定类型的队列，指定类型的队列只能存放同类型的消息。<br /><br /><strong>队列间的消息传递</strong><br />	Streams propagations能够将消息从一个队列传递到另一个队列，这些队列可以在同一个数据库中，也可以在不同数据库中。传递哪些消息同样由规则确定。<br /><br /><strong>消费消息</strong><br />	当消息从队列中出队时将被消费。应用过程（apply process）隐式的将消息出队，而用户、应用程序或是消息客户端显式的将消息出队。消费消息的数据库被称为目标数据库（destination database），目标数据库和源数据库可以是同一个。<br /><br /><br /><strong>Streams有什么用？<br /><br />消息队列</strong><br />	Oracle Streams 高级队列（AQ）使用户程序能将消息入队，传递到目的地，并且在目标数据库中将消息出队。AQ可设置为只能存储单一类型的消息，也可设置为可存储ANYDATA类型的消息，绝大部分的消息类型都可包装为ANYDATA类型以存储到ANYDATA队列。AQ遵循消息队列系统规范，诸如：点对点模式，订阅/发布模式，路由功能，广域网消息传播，消息转换，以及消息网关等。<br />	在数据库中创建队列后，应用程序显式的将消息放入队列，订阅程序或消息客户端可以立即接收到该消息。若想在远程订阅源数据库中发布的消息，可在远程数据库中创建一个队列，通过队列间的消息传递交互信息，远端程序便可使用本地队列接收到消息。另外，远端程序也可通过各种标准协议直接从源数据库队列中接收到消息。<br /><br /><strong>数据复制</strong><br />	Streams能够捕获到数据库中因DML和DDL操作引起的数据变更，并可将这些数据变更复制到其他数据库中。Streams 捕获进程捕获到源数据库中的数据变更并将这些信息格式化为LCR，通过AQ传递到目标数据库。<br />	目标数据库接收到数据变更消息后，可以对自身数据做出同样的DML或DDL操作，这样便可实现多个数据库之间的数据复制。即使彼此间表结构和数据都不同，也可完成同样的功能。<br /><br /><strong>事件管理和通知</strong><br />	应用程序能将事件描述包装为消息并显式的放入队列，而Streams 捕获进程能捕获到数据库DML或DDL事件并将其转化为LCR。Propagations 通过各种队列将消息传播到目的地，最后，用户程序或应用过程将消息出队。若必要的话，应用过程可以将出队的消息再次入队。<br />	通过配置，我们能指定当消息被消费后仍然驻留在队列中的时间。<br />	Streams 捕获进程、Propagations（传播）、应用过程、消息客户端都是基于规则的。Oracle中内置有规则引擎以计算何种事件将被捕获并传播。当捕获进程根据规则捕获到事件，将事件描述包装为消息并放入队列，消息客户端或应用程序接收到消息后，可以通过发送email或是发送短信通知客户。<br /><br /><strong>数据保护</strong><br />	要想保护数据，创建一个备份数据库是常见的解决方案。一旦发生人为或自然因素引起的灾难性后果，使用备份数据库能很快的恢复数据。Streams为此提供了高扩展性、高可用性的功能。<br />	此外，我们还可以使用与Streams采用同一架构的Oracle Data Guard，创建并维护与生产环境数据库相同的备份数据库。通过LCR的交互使备份数据库始终与生产环境数据库保持一致，并且备份数据库对外开放读写权限，这就使得备份数据库成为生产环境数据库的有力补充。<br /><br /><strong>数据库升级和维护</strong><br />	通过Oracle Streams，我们只需使数据库关闭极短时间甚至不需关闭，便可完成数据库的升级和维护操作。维护操作包括将数据库移植到其他平台，改变数据库的字符集，修改schema信息，给Oracle打补丁等。
          <br/>
          <span style="color:red;">
            <a href="http://shevliu.javaeye.com/blog/190189#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 06 May 2008 14:10:35 +0800</pubDate>
        <link>http://shevliu.javaeye.com/blog/190189</link>
        <guid>http://shevliu.javaeye.com/blog/190189</guid>
      </item>
  </channel>
</rss>