oracle工作机制,ORACLE的工作机制

ORACLE的工作机制

ORACLE 的工作机制-1肖亚峰(xyf_tck)我们从一个用户请求开始讲,ORACLE 的简要的工作机制是怎样的,首先一个用户进程发出一个连接请求,如果使用的是主机命名或者是本地服务命中的主机名使用的是机器名(非 IP 地址),那么这个请求都会通过 DNS 服务器或 HOST 文件的服务名解析然后传送到 ORACLE 监听进程,监听进程接收到用户请求后会采取两种方式来处理这个用户请求,下面我们分专用服务器和共享服务器分别采用这两种方式时的情况来讲:专用服务器模式下:一种方式是监听进程接收到用户进程请求后,产生一个新的专用服务器进程,并且将对用户进程的所有控制信息传给此服务器进程,也就是说新建的服务器进程继承了监听进程的信息,然后这个服务器进程给用户进程发一个 RESEND 包,通知用户进程可以开始给它发信息了,用户进程给这个新建的服务器进程发一个 CONNECT 包,服务器进程再以 ACCEPT 包回应用户进程,至此,用户进程正式与服务器进程确定连接。我们把这种连接叫做 HAND-OFF 连接,也叫转换连接。另一种方式是监听进程接收到用户进程的请求后产生一个新的专用服务器进程,这个服务器进程选用一个 TCP/IP 端口来控制与用户进程的交互,然后将此信息回传给监听进程,监听进程再将此信息传给用户进程,用户进程使用这个端口给服务器进程发送一个 CONNECT 包,服务器进程再给用户进程发送一个ACCEPT 包,至此,用户进程可以正式向服务器进程发送信息了。这种方式我们叫做重定向连接。HAND-OFF 连接需要系统平台具有进程继承的能力,为了使 WINDOWS NT/2000 支持HAND-OFF 必须在 HKEY_LOCAL_MACHINESOFTWAREORACLEHOMEX 中设置USE_SHARED_SOCKET。共享服务器模式下:只有重定向连接的方式,工作方式是监听进程接收到用户进程的请求后产生一个新的调度进程,这个调度进程选用一个 TCP/IP 端口来控制与用户进程的交互,然后将此信息回传给监听进程,监听进程再将此信息传给用户进程,用户进程使用这个端口给调度进程发送一个 CONNECT 包,调度进程再给用户进程发送一个 ACCEPT 包,至此,用户进程可以正式向调度进程发送信息了。可以通过设置 MAX_DISPIATCHERS 这个参数来确定调度进程的最大数目,如果调度进程的个数已经达到了最大,或者已有的调度进程不是满负荷,监听进程将不再创建新的调度进程,而是让其中一个调度进程选用一个 TCP/IP端口来与此用户进程交互。调度进程每接收一个用户进程请求都会在监听进程处作一个登记,以便监听进程能够均衡每个调度进程的负荷,所有的用户进程请求将分别在有限的调度进程中排队,所有调度进程再顺序的把各自队列中的部分用户进程请求放入同一个请求队列,等候多个 ORACLE 的共享服务器进程进行处理(可以通过 SHARED_SERVERS 参数设置共享服务器进程的个数) ,也就是说所有的调度进程共享同一个请求队列,共享服务器模式下一个实例只有一个请求队列,共享服务器进程处理完用户进程的请求后将根据用户进程请求取自不同的调度进程将返回结果放入不同的响应队列,也就是说有多少调度进程就有多少响应队列,然后各个调度进程从各自的响应队列中将结果取出再返回给用户进程。以上我们讲完了用户与 ORACLE 的连接方式,下面我们要讲 ORACLE 服务器进程如何处理用户进程的请求,当一个用户进程发出了一条 SQL 语句:UPDATE TABBLEA SET SALARY=SALARY*2;首先服务器进程将对该语句进行检查语句有效性的语法检查和确保语句能够正常运行的语义检查,首先检查该语句的语法的正确性(语法检查) ,接着对照数据字典对语句中涉及的表、索引、视图等对象及用户的权限进行检查(语义检查) ,如果以上任一检查没有通过,就返回一个错误,但不会明确的指出是语法检查出错还是语义检查出错,它只会返回一个 ORA-*的错误码。如果检查通过以后,服务器进程把这条语句的字符转换成 ASCII 等效数字码(注意 SQL 中使用*是个例外,如果表的字段改变了,同样是SELECT * FROM TABLEA 转换成的 ASCII 是不同的,其实它在语义检查时就明确的变成了操作具体字段的 SQL 语句了) ,接着这个 ASCII 码被传递给一个 HASH 函数,并返回一个 HASH值,服务器进程将到 SHARED POOL 的共享 PL/SQL 区去查找是否存在同样的 HASH 值,如果存在,服务器进程将使用这条语句已高速缓存在 SHARED POOL 中的已分析过的版本来执行(软解析) ,如果不存在,则必须进行以下两个步骤:语句的优化(生成执行计划) 和生成执行编码:服务器进程根据 ORACLE 选用的优化模式以及数据字典中是否存在相应对象的统计数据和是否使用了存储大纲来生成一个执行计划或从存储大纲中选用一个执行计划,最后再生成一个编译代码(硬解析) 。 (这里要注意的是,语法语义分析在前,计算HASH_VALUE 在后,算出 HASH_VALUE 后只要找到相同的 HASH_VALUE 就使用这条缓存执行计划,语义分析在前确保了用户的使用权限等问题,不存在算出 HASH_VALUE,再找到相同 HASH_VALUE 缓存执行计划而不能使用的情况。也不是先算 HASH_VALUE,然后找缓存执行计划,找到后再语义检查这个步骤也是错的)ORACLE 将这条语句的本身实际文本、HASH 值、编译代码、与此语句相关联的任何统计数据和该语句的执行计划缓存在 SHARED POOL 的共享 PL/SQL 区。V$librarycache 中的几个参数解释 Pins: (Execution)即 SQL 实际执行的次数,不包括用户提交的语法语义检查失败的 SQL。Reloads: (Parse)未找到相同HASH_VALUE 的次数,即必须进行硬解析的次数。Invalidations: (Parse)因对象更改,使得所有引用这个对象的缓存执行计划失效而必须再次硬解析的次数。只要 DDL 更改了一个对象,所有与此有关的缓存在共享池中执行计划都将立即失效,它的失效不是在下次执行 SQL 时才发现其失效,而是 DDL 更改对象后立即就失效。主要表现在 DDL 发生后 v$sql 的HASH_VALUE 仍保持不变,但 PLAN_HASH_VALUE 立即变为 0,再次运行 SQL 语句时则会向v$sql 插入一条新的缓冲记录 HASH_VALUE,PLAN_HASH_VALUE 都重新计算。原来的缓冲记录仍然还存在。服务器进程通过 SHARED POOL 锁存器来申请可以向哪些共享 PL/SQL 区中缓存这些内容,也就是说被 SHARED POOL 锁存器锁定的 PL/SQL 区中的块不可被覆盖,因为这些块可能正在被其它进程所使用。在 SQL 分析阶段将用到 LIBRARY CACHE,从数据字典中核对表、索引、视图及用户的权限的时候,需要将数据字典从磁盘读入 LIBRARY CACHE,因此,在读入之前也要使用 LIBRARY CACHE 锁存器来申请用于缓存数据字典。ORACLE 的工作机制-2肖亚峰(xyf_tck)生成编译代码之后,接着下一步服务器进程要准备开始更新数据,服务器进程将到 DB BUFFER 中查找是否有相关对象的缓存数据,下面分两个可能进行解释:如果没有,服务器进程将在表头部请求一些行锁,如果成功加锁,服务器进程将从数据文件中读入这些行所在的第一个数据块(db block)(DB BLOCK 是 ORACLE 的最小操作单元,即使你想要的数据只是 DB BLOCK 中很多行中的一行或几行,ORACLE 也会把这个 DB BLOCK中的所有行都读入 DB BUFFER 中)放入 DB BUFFER 中空闲的区域或者覆盖已被挤出 LRU 列表的非脏数据块缓冲区,并且排列在 LRU 列表的头部,如果这些非脏数据缓冲区写完也不能满足新数据的请求时,会立即触发 DBWN 进程将脏数据列表中指向的缓冲块写入数据文件,并且清洗掉这些缓冲区,来腾出空间缓冲新读入的数据,也就是在放入 DB BUFFER 之前也是要先申请 DB BUFFER 中的锁存器,成功锁定后,再写入 DB BUFFER,然后把这个块的头部事务列表及 SCN 信息及被影响的行数据原值写入回滚段中,以便 ORACLE 在ROLLBACK 时可以利用当前数据块和回滚段重构数据块的前映像 或递归重构出前前映像来实现读一致性。 (回滚段可以存储在专门的回滚表空间中,这个表空间由一个或多个物理文件组成,并专用于回滚表空间,回滚段也可在其它表空间中的数据文件中开辟。 )然后在 LOG BUFFER 中生成日志,服务器程将该语句影响的被读入 DB BUFFER 块中的这些行的 ROWID 及将要更新的原值和新值及 SCN 等信息, 以及回滚段的修改信息 (即对某某回滚段地址进行了什么修改)逐条的写入 REDO LOG BUFFER,在写入 REDO LOG BUFFER 之前也是先请求 REDO LOG BUFFER 块的锁存器,成功锁定之后才开始把 REDOLOG 写入 REDOLOG BUFFER。当写入达到 REDO LOG BUFFER 大小的三分之一或写入量达到 1M 或超过三秒后或发生检查点时或者 COMMIT 时或者 DBWN 之前触发 LGWR 进程,LGWR 将把 REDO LOG BUFFER 中的数据写入磁盘上的重做日志文件,已被写入重做日志文件的 REDO LOG BUFFER中的块上的锁存器被释放,并可被后来写入的信息所覆盖。回滚段其实也有 BUFFER(在DB BUFFER 中开辟) ,回滚段 BUFFER 中的内容是最早向磁盘上回滚段中写的,写完这些才会生成日志 BUFFER 中的内容,原因是日志中必须要记录回滚段的新旧变化以便在恢复时从日志中的记录的回滚段新旧变化对回滚段再次重写,记住,REDO 不光是对数据文件依据日志文件重写,也要依据日志文件对回滚段重写,而且重写回滚段要先于重写数据文件,要理解 REDO 就是重来一遍,所谓重来一遍就要跟正常的的先后顺利一样重做一遍(正常的操作中的顺序就是先读入 DB BUFFER,写回滚段 buffer,后写回滚段,后写日志 BUFFER,后改写 DB BUFFER,后写日志最后写数据文件)区别是 REDO 时不用再记日志了,这样解释后相信大家应该理解为什么日志中也必须要记录回滚段的信息了,只有这样才可以对正常操作中的一个 ROLLBACK 动作进行恢复,即在 REDO 过程中利用即时重写的数据块和回滚段重构出一个当时适用的前镜像来 rollback。当一个重做日志文件写满后,LGWR 将切换到下一个重做日志文件,重做日志文件也是循环工作方式。如果是归档模式,归档进程还将前一个写满的重做日志进程写入归档日志文件。当 DB BUFFER 改写之后,服务器进程在脏数据列表中建立一条指向此 DB BUFFER 缓冲块的指针。接着服务器进程会从数据文件读入第二个数据块(db block)重复以上读入,建立回滚段,写 LOG BUFFER,改写 DB BUFFER,放入脏列表的动作,当脏数据列表达到一定长度时,DBWN 进程将脏数据列表中指向的缓冲块全部写入数据文件,也就是释放加在这些 DB BUFER 块上的锁存器,并在修改相应块的头部的 SCN 号(一次 UPDATE 操作只对应一个 SCN) 。前面说过 DBWN 动作之前会先触发LGWR,这用以确保写入数据文件的改变首先会被记录在日志文件中。实际上 ORACLE 可以从数据文件中一次读入多个块放入 DB BUFFER,然后再对这些块建回滚段、再记日志等等,也就是每次操作的对象是 DB BLOCK 的复数,而不仅限于一次操作一个 DB BLO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值