2007年3月31日星期六

win2003下oracle 9.2.0.8 用dbca建库时出现ora-29807错误

很少在windows下部署oracle的生产库,今天在win2003下oracle 9.2.0.8 用dbca建库时出现ora-29807错误记得这个bug很早就出现过,没有想到在9.2.0.8下还没有修正,特地又去metalink上查了一下,解决方法如下,记录在此备忘:

Problem
~~~~~~~

While using Database Creation Assistant (DBCA) to create a database (custom or template) after patchset 9.2.0.2.0 or 9.2.0.3.0 has been applied, ORA-29807 'specified operator does not exist' is encountered during 'create data dictionary views.'

It has been determined that this error is being raised while DBCA is running the script prvtxml.plb.

Prvtxml.plb is a script which creates a particular package body. This script is called from the catxml.sql script - which in turn is called by the catproc.sql script - run automatically when creating a database using DBCA.

Workaround
~~~~~~~~~~
This workaround can be implemented either before invoking the DBCA or after the ORA-29807 has been encountered.

1. Go to the script catxml.sql and comment out the line which will run prvtxml.plb
2a. If the script has been edited before invoking DBCA, it is now safe to proceed with invoking DBCA

OR

2b. If the script has been edited after the ORA-29807 is encountered, go back to your DBCA screen and click 'Ignore'

3. The database creation using DBCA should now proceed without additional errors.

4. Once DBCA has completed database creation, remember to run the 'prvtxml.plb' script independently, as the user SYS.

5. Check whether there are invalid objects:select * from dba_objects where owner = 'SYS' and status = 'INVALID' ;If so, run the 'utlrp.sql' script to validate those objects.

2007年1月28日星期日

解决winxp(sp2)下因防火墙导致的oracle客户端无法连接数据库问题的方法

解决步骤如下:
1、在winxp的防火墙上打开1521端口(默认的监听端口,如果你更改了listener的默认监听端口,打开相应的端口即可);
2、在系统环境变量中设置 USE_SHARED_SOCKET = TRUE 或者 设置到注册表中以下位置
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME<#> (Release 8i or higher)

(利用了Winsock 2的端口共享特性)

以上设置需要重起机器;另外,这样设置后停止listener不会中断已有的session,但是重起的时候会强制断开已有的session。

原话:The listener can be stopped without interupting the connected sessions, but itcannot be restarted without forcibly disconnecting connected sessions first.


更进一步的信息可以参考metalink:124140.1

2007年1月27日星期六

理解Oracle9i中的监听动态注册

在Oracle9i中,使用命令lsnrctl status可以看到如下例子: Service "lrdb" has 2 instance(s). Instance "lrdb", status UNKNOWN, has 1 handler(s) for this service... Instance "lrdb", status READY, has 1 handler(s) for this service... 这是Oracle9i监听器行为的不同之处的第一个线索,因为Instance "lrdb"出现了两次。出现额外条目是因为,数据库在启动时通过一个被称为动态注册的进程在监听器中注册信息。相应地,如果数据库通过listener.ora 文件中的信息在监听器中注册数据库着称为静态注册。在上面的输出中,状态UNKNOWN值的时静态注册的设置。这是监听器用来表明它不知道关于该实例的任何信息的方式,只有当客户发出连接请求时,它才检查该实例是否存在。 动态注册的数据库通过状态信息中的状态READY或状态BLOCKED(对于一个备用数据库)来指明。不管何时数据库数据库关闭,动态注册的数据库都会动态地从监听器注销,而与之相关的信息将从状态列表中消失。这样,不管数据库是在运行还是已经关闭,监听器总是知道它的状态。该信息将被用于连接请求的回退(fallback)和负载平衡。自我注册功能是不能被关闭的(至少在任何可见的文档中是这样),由于该功能带来的好处,因此不能关闭它也并不是件坏事。当您可以免费获得数据库的自我注册功能时,为什么还需要listener.ora文件中的静态注册条目呢?您对此感到疑惑,是吗?答案是:除了几种例外情况外,您根本不需要执行静态注册。这样的结果是,只要使用默认的监听器端口1521,您就不再需要listener.ora文件。然而,当(且仅当)要把日志文件和跟踪信息保存到标准目录中时,您或许仍然会使用listener.ora文件。 下面是数据库的自我注册过程(假设在数据库启动之前,监听器已经启动并在正常运行)。无论何时启动一个数据库,默认地都有两条信息注册到监听器中:实例和服务。 注册到监听器中的实例值从init.ora文件中的instance_name参数取得。如果该参数没有设定值,那么它将取init.ora 文件中的db_name的值。在只有单个实例运行的情况下,您可以不必设置该参数,但最好将其设置为db_name的值,以充分利用动态注册功能。然后,如果在RAC中配置,您必须将集群中每个实例的instance_name参数设置为一个唯一的值。 注册到监听器中的服务值从init.ora文件中的参数service_names取得。如果该参数没有设定值,数据库将拼接 init.ora文件中的db_name和db_domain的值来注册自己。如果选择提供service_names值,您可以使用完全限定的名称(比如lrdb.oracle.com)或缩写的名称(比如lrdb)。如果选择缩写的名称并设置了db_domain参数,注册到监听器中的服务将是service_name值和db_domain值的拼接。例如下面的设置将导致服务lrdb.oracle.com 被注册到监听器中: db_domain=oracle.com service_name=lrdb 可选择的,您可以在service_names参数中指定多个服务值,值之间用逗号格开;这对于共享服务器配置是很有用的。如果需要执行连接时故障转移或负载均衡,或者想要在RAC中配置在实例之间透明地分布连接,那么使用service_names 参数将是必要的。为启用这些功能,您只需要将每个实例的数据库参数文件中的service_names设置为同一个值,并在客户端连接请求的service_name设置中引用该值。 为初始化参数service_names和instance_name设置显式的值是个很好的实践,尽管如果您没有设置它们,Oracle也会为动态注册而生成默认值(基于db_name和db_main)。这样做的原因是,如果监听器在数据库启动之后重新启动,其动态注册行为将会有一些微妙的区别.如果监听器在数据库运行之后重新启动,你们仅当您在init.ora文件中显式地设置了service_names和instance_name的值时,每个数据库的PMON进程才会在很短的时间之后自动注册数据库。如果没有显式设置service_names和instance_name的值,那么仅当数据库在监听器运行之后启动时,动态注册才会发生;在这种情况下,如果监听器后来发生了重启,动态注册信息将会丢失。 显然,最后在启动任何数据库之前启动服务器上的监听器,并完全避免监听器的重启。另外,您还可以在SQL*PLUS中使用ALTER SYSTEM REGISTER命令,在数据库打开时的任何时候,手工地在监听器中注册服务值。这个命令对于替换因监听器重启而丢失地服务值很有用,并且它所注册地值与在数据库启动时由动态注册所设置的值完全一样。 总而言之,Oracle9i通过listener.ora中的GLOBAL_DBNAME向外提供静态服务,通过PMON读初始化参数service_names、 instance_name向外提供动态(真实在运行的)服务。举例如下: listener.ora文件内容 SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /oracle/product/9.2.0.4) (PROGRAM = extproc) ) (SID_DESC = (GLOBAL_DBNAME = lrdb) (ORACLE_HOME = /oracle/product/9.2.0.4) (SID_NAME = lrdb) ) (SID_DESC = (GLOBAL_DBNAME = gsid) (ORACLE_HOME = /oracle/product/9.2.0.4) (SID_NAME = lrdb) ) ) 该文件使得这个单实例的数据库lrdb,向外提供了两个服务:lrdb和gsid 初始化参数设置:instance_name=lrdb service_name=lrdb,gsid 所以动态注册时也会对外提供两个服务:lrdb和gsid 最后通过lsnrctl status看到的情况就是: Service "gsid" has 2 instance(s). Instance "lrdb", status UNKNOWN, has 1 handler(s) for this service... Instance "lrdb", status READY, has 1 handler(s) for this service... Service "lrdb" has 2 instance(s). Instance "lrdb", status UNKNOWN, has 1 handler(s) for this service... Instance "lrdb", status READY, has 1 handler(s) for this service... 对外提供的服务gsid和lrdb都有两个实例(一个静态注册一个动态注册),状态都分别是UNKNOWN和READY。 对于客户端来说,它不用关心数据库的名字、实例名到底是什么,它只需要知道数据库对外提供的服务名就行了,这个名字可能和实例名一样,也可能不一样。