Hey!! Sky!

Jun 06, 2006

使用 PL/SQL Developer 引发 ORA-600 [17113]

    今天翔哥在 QQ 上发过来一张图,一看是在 PL/SQL Developer 上创建序列时发生 ORA-600 [17113] 错误。这种内部错误,大多比较头痛,Google 了一下,找了下面一段文字:



PURPOSE:
  This article discusses the internal error "ORA-600 [17113]", what
  it means and possible actions. The information here is only applicable
  to the versions listed and is provided only for guidance.


ERROR:
  ORA-600 [17113] [a]


VERSIONS:
  versions 7.0 to 10.1


DESCRIPTION:


  An error occurred when getting a new extent while adding to a heap.


  The heap descriptor is uninitialized.


ARGUMENTS:
  Arg [a] Always 0


FUNCTIONALITY:
  HEAP MANAGER


IMPACT:
  PROCESS FAILURE
  MEMORY CORRUPTION
  NON DATA CORRUPTIVE - No underlying data corruption.


SUGGESTIONS:


  These errors can occur after the actual Oracle in-memory corruption
  has taken place.


  Hence the processes that report the error may not be the ones that
  caused it.


  Check for third party software being used to access the database.
  This error can be reported when there are compatibility issues
  between third party software and the database.


  Check for other messages preceeding this message.


  Check if the problem is reproducable.


  Run memory diagnostics on all system hardware.


  If the Known Issues section below does not help in terms of identifying
  a solution, please submit the trace files and alert.log to Oracle
  Support Services for further analysis.


  Known Issues:
  Bug# 3488371   See Note 3488371.8
      OERI[17113] can occur during import of materialized views
      Fixed: 10.1.0.4, 10.2


  Bug# 3066549   See Note 3066549.8
      OERI[17113] / memory corruption can occur selecting from a view
      Fixed: 9.2.0.5, 10.1.0.2


  Bug# 2298968 +  See Note 2298968.8
      Client side memory leak for 32<->;64 bit SELECTs
      Fixed: 9.0.1.4, 9.2.0.1


  Bug# 2248904   See Note 2248904.8
      Memory corrupt possible during optimization of distributed query
      Fixed: 8.1.7.4, 9.0.1.4, 9.2.0.1


  Bug# 1964934   See Note 1964934.8
      Memory corruption possible using INSERT /*+ APPEND */ over DBLINK
      Fixed: 8.1.7.4, 9.0.1.3, 9.2.0.1


  Bug# 1460657   See Note 1460657.8
      OERI:17113 creating partitioned OBJECT MVIEW with LOB column
      Fixed: 9.0.1.0


    上文说到,该问题是第三方软件和 Oracle 之间的兼容性所引起的,再看了下 google 出来的结果大多和 PL/SQL Developer 有关。


解决方法:
    1. 将 PL/SQL Developer 升级到新版本,一般发生该问题的都是 5.X,升级到新版本,该问题就解决了。
    2. 将编译时错误提示关闭:Tools->Preferences->Debugger 将 Add debug information when compiling 前的钩去掉。


参考:
http://www.cnoug.org/viewthread.php?tid=8319
http://bbs.chinaunix.net/viewthread.php?tid=570429
http://keweixing.itpub.net/post/7901/48707

May 30, 2006

Oracle 数据库联机日志文件丢失处理方法

    这篇是 Remen 在 CU 上的精华贴,今天正好碰到群里有人问这个问题,回过来又看了下这篇文章,做了下实验,感觉不错,这篇比另外一篇更详细,也更准确,网上关于联机日志恢复的文章好像就这么两篇。
    今天碰到的问题是,无归档、无备份,正常关闭数据库情况下删除了所有联机日志。因为正常关闭,数据库是一致的,处理就比较简单了,就是要让联机日志文件生成。
    1.因为当前日志也丢失了,非当前日志可以通过 alter database clear logfile group n 来处理;而当前日志,如果有备份才可以通过还原备份,再加上 alter database clear unarchived logfile group n 来恢复。现在没有备份,所以该方法否决。
    2.通过 alter database backup controlfile to trace 获得的 SQL 脚本来重建 controlfile。因为要重新生成联机日志,所以要用 resetlogs 的那个脚本,重建之后,用 alter database open resetlogs 打开。注意:打开之后 tempfile 可能会丢失,需要重新添加进去。然后全备一下。
    3.最后,也是最简单的方法:通过 recover database until cancel 执行部分恢复(由于数据库是一致的,其实不用恢复,只是为了后面的 open resetlogs),再 alter database open resetlogs 打开时据库。
    以上三种方法对于归档/非归档的数据库都是适用的。

试验一:用命令清空日志组方法
1、        查看原来表中数据
SQL>; conn test/test
Connected.
SQL>; select * from test;

       TEL
----------
         1
         2
         3
2、插入新数据
SQL>; insert into test values(4);
1 row created.
SQL>; commit;
Commit complete.
SQL>;
3、        正常关闭数据库
4、        利用os command删除所有redo文件
5、        启动数据库
SQL>; startup
ORACLE instance started.
Total System Global Area  353862792 bytes
Fixed Size                   730248 bytes
Variable Size             285212672 bytes
Database Buffers           67108864 bytes
Redo Buffers                 811008 bytes
Database mounted.
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'
6、        查看当前日志状态
SQL>; select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIME
------------- ----------
         1          1          2  104857600          1 YES INACTIVE
       487837 01-9月 -05

         2          1          4  104857600          1 NO  CURRENT
       487955 01-9月 -05

         3          1          3  104857600          1 YES INACTIVE
       487839 01-9月 -05
看来redo01.log不是当前日志,对于这类非当前日志可以直接clear,系统会重新自动生成一个redo文件

7、SQL>; alter database clear logfile group 1;
Database altered.
7、        继续启动db
SQL>; alter database open;
alter database open
*
ERROR at line 1:
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'
8、        看来redo也得恢复,但是redo02是当前redo,直接clear是不行的
SQL>; alter database clear logfile group 2;
alter database clear logfile group 2
*
ERROR at line 1:
ORA-00350: log 2 of thread 1 needs to be archived
ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'
尝试clear unarchived logfile group ,报错:
SQL>; alter database clear unarchived logfile group 2;
alter database clear unarchived logfile group 2
*
ERROR at line 1:
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'
ORA-27037: unable to obtain file status
SVR4 Error: 2: No such file or directory
Additional information: 3
看来他是因为找不到这个文件,从有效的备份中cp一个过来看看
SQL>; host cp /T3/ORACLE/oradatabak/redo02* /T3/ORACLE/oradata/ORA9

SQL>; alter database clear unarchived logfile group 2;

Database altered.
搞定……….

9、        按照oracle的某些做法也是可以的
SQL>; alter database clear unarchived logfile group 1 unrecoverable datafile;

Database altered.

10、但是对于非当前日志就都可以,下面看看redo03
SQL>;  alter database clear logfile group 3;

Database altered.

结论:
如果数据库是正常shutdown,非当前日志都可以直接clear来重新生成,而且不丢失数据,因为正常关闭db,数据已经写入dbf文件了。唯独当前日志不可以,当前日志必须首先从有效的备份中拷贝一个日志文件过来,然后用
alter database clear unarchived logfile group n 或alter database clear unarchived logfile group n,除此之外,还可以用下面的方法来做

方法二:用cancel模式恢复数据库
前面的出错提示,步骤都一样,唯独恢复的方法不一样
SQL>; startup
ORACLE instance started.
Total System Global Area  353862792 bytes
Fixed Size                   730248 bytes
Variable Size             285212672 bytes
Database Buffers           67108864 bytes
Redo Buffers                 811008 bytes
Database mounted.
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'
看看丢失了哪些redo
SQL>; host ls /T3/ORACLE/oradarta/ORA9/redo*
/T3/ORACLE/oradarta/ORA9/redo*: No such file or directory
看来redo都丢了
直接recover
SQL>; recover database until cancel;
Media recovery complete.
这个时候redo还没有生成
SQL>; host ls /T3/ORACLE/oradata/ORA9/redo*
/T3/ORACLE/oradata/ORA9/redo*: No such file or directory
启动数据库
SQL>; alter database open ;
alter database open
*
ERROR at line 1:
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open

SQL>;  alter database open resetlogs;
Database altered.
(注意,这里必须用resetlogs,否则会错误的)
SQL>; alter database open noresetlogs;
alter database open noresetlogs
*
ERROR at line 1:
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'
SQL>;
Resetlogs其实就是根据控制文件让系统自动重新生成redo,如果noresetlog的话,就不会重新生成redo,缺少了文件,db自然无法启动)
SQL>;  host ls /T3/ORACLE/oradata/ORA9/redo*
/T3/ORACLE/oradata/ORA9/redo01.log  /T3/ORACLE/oradata/ORA9/redo02.log  
/T3/ORACLE/oradata/ORA9/redo03.log
SQL>;
检验
SQL>; select * from test.test;

       TEL
----------
         1
         2
         3
         4
SQL>;
数据一点儿都没有丢失

结论:
如果数据库是正常关闭的,用recover database until cancel可以轻松恢复或者说重新建立所有的redo,不再区分是否是当前日志,而且由于正常关闭,不会丢失任何数据,唯一可能丢失的情况就是如果日志还没有归档
这种恢复方法 由于要resetlogs,所以在恢复完成后,日志清零,以前的备份不再起作用,所以建议立即备份
SQL>; archive log list;
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /T3/ORACLE/arch
Oldest online log sequence     0
Next log sequence to archive   1
Current log sequence           1
SQL>;


实验三:通过重新生成控制文件来恢复redo
前面的都一样,只是处理方法不一样
SQL>; startup
ORACLE instance started.

Total System Global Area  353862792 bytes
Fixed Size                   730248 bytes
Variable Size             285212672 bytes
Database Buffers           67108864 bytes
Redo Buffers                 811008 bytes
Database mounted.
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'

SQL>; alter database backup controlfile to trace;

Database altered.

SQL>; shutdown immediate
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
SQL>;
2、        修改一下刚才生成的那个文件
CREATE CONTROLFILE REUSE DATABASE "ORA9"  RESETLOGS  ARCHIVELOG
--  SET STANDBY TO MAXIMIZE PERFORMANCE
    MAXLOGFILES 50
    MAXLOGMEMBERS 5
    MAXDATAFILES 100
    MAXINSTANCES 1
    MAXLOGHISTORY 226
LOGFILE
  GROUP 1 '/T3/ORACLE/oradata/ORA9/redo01.log'  SIZE 100M,
  GROUP 2 '/T3/ORACLE/oradata/ORA9/redo02.log'  SIZE 100M,
  GROUP 3 '/T3/ORACLE/oradata/ORA9/redo03.log'  SIZE 100M
-- STANDBY LOGFILE
DATAFILE
  '/T3/ORACLE/oradata/ORA9/system01.dbf',
  '/T3/ORACLE/oradata/ORA9/undotbs01.dbf',
  '/T3/ORACLE/oradata/ORA9/cwmlite01.dbf',
  '/T3/ORACLE/oradata/ORA9/drsys01.dbf',
  '/T3/ORACLE/oradata/ORA9/example01.dbf',
  '/T3/ORACLE/oradata/ORA9/indx01.dbf',
  '/T3/ORACLE/oradata/ORA9/odm01.dbf',
  '/T3/ORACLE/oradata/ORA9/tools01.dbf',
  '/T3/ORACLE/oradata/ORA9/users01.dbf',
  '/T3/ORACLE/oradata/ORA9/xdb01.dbf',
  '/T3/ORACLE/oradata/ORA9/test01.dbf'
CHARACTER SET ZHS16GBK
;
另存为一个脚本,运行他
SQL>; @clone.sql
Control file created.
SQL>; alter database open resetlogs;
Database altered.
SQL>;
搞定……………

结论:这种方法的关键是重新创建控制文件,后面的步骤和前面的道理一样的

前面的三种方法都是假设db是正常关闭的,数据已经写入数据库文件中,所以不会由数据存在redo种,所以clear的话也不会有数据丢失


方法四:修改系统参数方法
1、        插入数据
SQL>; select * from test;

       TEL
----------
         1
         2
         3
         4

SQL>; insert into test values(5);

1 row created.

SQL>; commit;

Commit complete.

SQL>;
2、        强行关闭
SQL>; shutdown abort
ORACLE instance shut down.
SQL>;
3、        手工模拟删除redo
4、        启动db
SQL>; startup
ORACLE instance started.

Total System Global Area  353862792 bytes
Fixed Size                   730248 bytes
Variable Size             285212672 bytes
Database Buffers           67108864 bytes
Redo Buffers                 811008 bytes
Database mounted.
ORA-00313: open failed for members of log group 3 of thread 1
ORA-00312: online log 3 thread 1: '/T3/ORACLE/oradata/ORA9/redo03.log'
ORA-27037: unable to obtain file status
SVR4 Error: 2: No such file or directory
Additional information: 3
5、        尝试使用前3中方法中最简单的
SQL>; recover database until cancel;
ORA-00279: change 550174 generated at 09/02/2005 16:00:19 needed for thread 1
ORA-00289: suggestion : /T3/ORACLE/arch/1_1.dbf
ORA-00280: change 550174 for thread 1 is in sequence #1
Specify log: {<RET>;=suggested | filename | AUTO | CANCEL}
看来不行
6、        修改init.ora,加入一行
_allow_resetlogs_corruption=true
7、        启动with pfile
SQL>; startup
ORACLE instance started.
Total System Global Area  320308312 bytes
Fixed Size                   730200 bytes
Variable Size             285212672 bytes
Database Buffers           33554432 bytes
Redo Buffers                 811008 bytes
Database mounted.
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open

SQL>; host ls /T3/ORACLE/oradata/ORA9/redo*
/T3/ORACLE/oradata/ORA9/redo*: No such file or directory
SQL>; alter database open resetlogs;
Database altered.

SQL>; host ls /T3/ORACLE/oradata/ORA9/redo*
/T3/ORACLE/oradata/ORA9/redo01.log  /T3/ORACLE/oradata/ORA9/redo02.log  
/T3/ORACLE/oradata/ORA9/redo03.log
8、        检验数据
SQL>; select * from test.test;

       TEL
----------
         1
         2
         3
         4

SQL>;
看到了吧,我们前面由于执行了SHUTDOWN ABORT,这时候对数据的修改还没有保存到数据文件中,虽然执行了COMMIT,这个时候还在联机日志中,等待CKPT触发DBWR写入DATAFILE,但是这个时候执行了SHUTDOWN ABORT,redo被删除后,里面的信息也就丢了,造成数据丢失
9、        备份,去掉那个参数


试验五:丢失当前日志组的成员
1、SQL>; select * from v$logfile;

    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         3         ONLINE
/T3/ORACLE/oradata/ORA9/redo03.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02.log

         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01.log


    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01a.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02a.log

         3         ONLINE
/T3/ORACLE/oradata/ORA9/redo03a.log

SQL>; select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIME
------------- ----------
         1          1          2  104857600          2 YES INACTIVE
       554599 02-9月 -05

         2          1          3  104857600          2 YES INACTIVE
       554601 02-9月 -05

         3          1          4  104857600          2 NO  CURRENT
       554603 02-9月 -05
SQL>;
3、        模拟插入数据
SQL>; conn test/test
Connected.
SQL>; select * from test;

       TEL
----------
         1
         2
         3
         4

SQL>; insert into test values(5);

1 row created.

SQL>; commit
  2  ;

Commit complete.
4、        shutdown db,模拟删除一个当前日志成员
$ cd oradata/ORA9
$ ls redo03*
redo03.log   redo03a.log
$ rm redo03a.log
5、        启动db,表面没有错误
SQL>; startup
ORACLE instance started.

Total System Global Area  353862792 bytes
Fixed Size                   730248 bytes
Variable Size             285212672 bytes
Database Buffers           67108864 bytes
Redo Buffers                 811008 bytes
Database mounted.
Database opened.
SQL>;
6、        查看日至成员
SQL>; select * from v$logfile;

    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         3         ONLINE
/T3/ORACLE/oradata/ORA9/redo03.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02.log

         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01.log


    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01a.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02a.log

         3 INVALID ONLINE
/T3/ORACLE/oradata/ORA9/redo03a.log
7、        删除出问题的联机日志文件
SQL>; alter database drop logfile member '/T3/ORACLE/oradata/ORA9/redo03a.log';
alter database drop logfile member '/T3/ORACLE/oradata/ORA9/redo03a.log'
*
ERROR at line 1:
ORA-01609: log 3 is the current log for thread 1 - cannot drop members
ORA-00312: online log 3 thread 1: '/T3/ORACLE/oradata/ORA9/redo03.log'
ORA-00312: online log 3 thread 1: '/T3/ORACLE/oradata/ORA9/redo03a.log'


SQL>;
看来当前日志成员是不允许删除的
SQL>; alter system switch logfile;

System altered.

SQL>; select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIME
------------- ----------
         1          1          5  104857600          2 NO  CURRENT
       557687 02-9月 -05

         2          1          3  104857600          2 YES INACTIVE
       554601 02-9月 -05

         3          1          4  104857600          2 YES ACTIVE
       554603 02-9月 -05


SQL>; alter database drop logfile member '/T3/ORACLE/oradata/ORA9/redo03a.log';

Database altered.

SQL>;  alter database add logfile member '/T3/ORACLE/oradata/ORA9/redo03a.log' to group 3;

Database altered.
SQL>; select * from v$logfile;

    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         3         ONLINE
/T3/ORACLE/oradata/ORA9/redo03.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02.log

         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01.log


    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01a.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02a.log

         3 INVALID ONLINE
/T3/ORACLE/oradata/ORA9/redo03a.log
看来还得切换一下日至
SQL>; alter system switch logfile;

System altered.
SQL>; select * from v$logfile;

    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         3         ONLINE
/T3/ORACLE/oradata/ORA9/redo03.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02.log

         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01.log


    GROUP# STATUS  TYPE
---------- ------- -------
MEMBER
--------------------------------------------------------------------------------
         1         ONLINE
/T3/ORACLE/oradata/ORA9/redo01a.log

         2         ONLINE
/T3/ORACLE/oradata/ORA9/redo02a.log

         3         ONLINE
/T3/ORACLE/oradata/ORA9/redo03a.log

至此,大功告成…………….

结论:
只要日志组的member不是一个,出现前面的4种可能性是非常小的,即使出现了也有相应的恢复方法,所以不必惊慌;
如果memer多于1个,即使坏了其中的几个,也不会 影响数据库的正常启动,启动后,再进行相应的操作即可, 所以这个时候每天察看alert.log就显得非常重要了。


Remen
2005.9.2


http://bbs.chinaunix.net/viewthread.php?tid=613223

May 26, 2006

两个 RMAN

    今天群里有人问关于 RMAN 的问题,在 RHEL 里,输入 RMAN target / ,提示 rman: can't open target。刚开始一看以为是 target 数据库没有打开,或者没有设置 oracle_sid 之类的环境变量而无法找到 taget 数据库。但总觉得这个错误信息有点奇怪,不像是 RMAN 或者 Oracle 的错误信息。在 google 搜索了一下,终于知道是怎么回事了。


    原来 RHEL 自己还带了个 RMAN 命令:


# whereis rman
rman: /usr/X11R6/bin/rman /usr/bin/X11/rman


    这个 RMAN 是一个开源项目,是将编译的 man pages 转换为可读格式的文件的:



PolyglotMan(1) PolyglotMan(1)


NAME
PolyglotMan, rman - reverse compile man pages from formatted form to a
number of source formats


SYNOPSIS
rman [ options ] [ file ]


DESCRIPTION
PolyglotMan takes man pages from most of the popular flavors of UNIX
and transforms them into any of a number of text source formats. Poly-
glotMan was formerly known as RosettaMan. The name of the binary is
still called rman , for scripts that depend on that name; mnemonically,
just think "reverse man". Previously PolyglotMan required pages to be
formatted by nroff prior to its processing. With version 3.0, it
prefers [tn]roff source and usually produces results that are better
yet. And source processing is the only way to translate tables. Source
format translation is not as mature as formatted, however, so try for-
matted translation as a backup.


In parsing [tn]roff source, one could implement an arbitrarily large
subset of [tn]roff, which I did not and will not do, so the results can


    既然知道了原因,那么解决方法也就很明了了:
    1.最笨的办法,将操作系统带的那个 RMAN 删除或者改名。
    2.在运行 Oracle 的 RMAN 时,给出完整路径
    3.修改 Oracle 用户的 .bash_profile,将 $ORACLE_HOME/bin 路径放到 $PATH 的最前面。

参考:
http://www.itpub.net/503204,1.html
http://www.cnoug.org/viewthread.php?tid=94122

May 19, 2006

日期的中文显示

    碰到了日期的中文显示问题,以前还真没想过用 to_char 直接显示中文日期的方法,今天一试出问题了,原来 Format 中指定 string 是要用 "" 包起来的。看看例子:



SQL> ed
Wrote file afiedt.buf


  1  select to_char(to_date('19530505','yyyymmdd'),'yyyy年mm月dd日')
  2* from dual
SQL> /
select to_char(to_date('19530505','yyyymmdd'),'yyyy年mm月dd日')
                                               *
ERROR at line 1:
ORA-01821: date format not recognized



    这种写法现在想想还真傻,呵呵,当然用 '' 包围起来那肯定是不行的,会和前面的 ' 冲突。查了下文档上面很清楚的写着哪些 Format 可以用,怎么用,还要多学习啊。



SQL> ed
Wrote file afiedt.buf


  1  select to_char(to_date('19530505','yyyymmdd'),'yyyy"年"mm"月"dd"日"') "Date
"
  2* from dual
SQL> /


Date
--------------------------------------------------------------------------------


1953年05月05日


    这下可以了,也可以修改环境变量 NLS_DATE_FORMAT ,变量 NLS_LANGUAGE 有默认的 NLS_DATE_FORMAT 格式,不过可以用 NLS_DATE_FORMAT 覆盖这个默认值,当然用 alter session 可以临时改变 session 的设置:



SQL> alter session set nls_date_format='yyyy"年"mm"月"dd"日"';


Session altered.


    修改之后,所有的日期类型会自动转换为 NLS_DATE_FORMAT 的格式显示出来。这个设置可以通过查询 NLS_SESSION_PARAMETERS 和 V$NLS_PARAMETERS 视图获得。NLS_INSTANCE_PARAMETERS 视图显示的是初始化参数中设置的格式,如果没有设置,就显示为空。NLS_DATABASE_PARAMETERS 应该是来自 sys.props$ 是数据库安装时的默认值。


    哈哈,记到这里,方便以后查询,下班咯。

May 17, 2006

Oracle 共享服务器(Shared Server / MTS)的配置

    9i 下的共享服务器 Shared Server(8i 中的多线程服务器 MTS )主要用在 OLTP 业务中,服务器进程每次处理业务只需很短的时间,大多在空闲状态,在这种情况下,可以用较少的资源,处理较多的用户请求。


共享服务器的配置
1.设置 DISPATCHERS 参数:
    在 pfile 中添加:


*.DISPATCHERS='(PROTOCOL=TCP)(SERVICE=SKYSH)(DISPATCHERS=2)(PROTOCOL=IPC)(DISPATCHERS=1)'

    以上方法启动之后,DISPATCHER 的端口是随机分配的,如果要固定每个 DISPATCHER 的端口,可以用一下方法:
    使用不同端口:


*.DISPATCHERS='(ADDRESS=(PROTOCOL=TCP)(PORT=5000))(DISPATCHERS=1)','(ADDRESS=(PROTOCOL=TCP)(PORT=5001))(DISPATCHERS=1)'

    使用相同端口:


*.dispatchers='(ADDRESS=(PROTOCOL=TCP)(PORT=5130))(SERVICE=SKYSHR)(DISPATCHERS=1)'


    如果是 spfile 启动,先用 create pfile from spfile 创建 pfile,修改好之后,再用 create spfile from pfile 创建 spfile。
    注:虽然 DISPATCHERS 是动态参数,但只能用 alter system set DISPATCHERS 来临时添加删除 dispatcher,重启之后又恢复原值,且不能使用 scope 参数。
    其中,SERVICE=SKYSH 参数可以不指定,如果不指定,则需要指定 service_names 和 instance_name 初始参数,当 instance 启动时,PMON 会动态将 SERVICE 或者 service_names 指定的值邦定到 LISTENER,并生成 dispatchers。
    DISPATCHERS=2 如果不指定,那么默认值是 1。
    PROTOCOL:当使用 Shared Server 连接时,必须通过 Oracle Net Services,即使客户端和数据库在同一台机子上,如果在 Windows NT 上,dispatchers 只能使用 TCP/IP 协议。


2.设置客户端 tnsnames.ora 文件:


SKY3 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.123)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = SKYSH.heysky.net)
      (SERVER = SHARED)
    )
  )

    其中,SERVICE_NAME = SKYSH.heysky.net 中的值必须是动态邦定的 service_name.db_domain,否则会产生 ORA-12523 错误:


ERROR:
ORA-12523: TNS:listener could not find instance appropriate for the client connection

    使用共享服务器连接,必须指定 (SERVER = SHARED),如果不指定,则作为 DEDICATE 连接。


3.SHARED_SERVERS 参数:
    该参数指定当 instance 启动时,初始生成的共享服务器进程数量,如果要使用共享服务器,该值必须大于 0,否则将产生 ORA-12520 错误:


ERROR:
ORA-12520: TNS:listener could not find available handler for requested type of server

    通过动态改变该参数,可以增加减少默认的共享服务器进程数量,或者在不停止数据库的情况下禁止共享服务器。当动态将其设置为 0 时,共享服务器进程在完成所有工作,并空闲一段时间之后终止,可以通过查看 v$shared_server 动态视图来查看共享服务器的状态。


4.其他一些相关参数:
    MAX_DISPATCHERS:最大 DISPATCHER 数量,默认值是 5,如果 DISPATCHERS 中设置的所有 DISPATCHER 数量之和大于 5,那么 MAX_DISPATCHERS 等于这个和数。


    MAX_SHARED_SERVERS:最大共享服务器进程,当初始分配的 SHARED_SERVERS 不够时,Oracle 会继续生成 共享服务器,直到这个最大值,当空闲时,Oracle 会终止空闲的进程,直到 SHARED_SERVERS 中指定的值为止。


    CIRCUITS:改值一般等于 SESSIONS 的数量。


    SHARED_SERVER_SESSIONS:共享服务器连接所能用的最大 SESSION 值,一般可以设置为小于 CIRCUITS and SESSIONS -5 的值,以便给 DEDICATE 连接留下一定的 SESSION 数。


5.一些注意事项:
    当 sysdba 已 shared server 连接时,不能执行 start up、shut down 或者 recovery 命令,否则可能出现如下错误:


ORA-00106: cannot startup/shutdown database when connected to a dispatcher

    当使用共享服务器的时候,需要设置 LARGE_POOL_SIZE 参数,并且要足够,因为,当使用共享服务器的时候,本来在 PGA 中的 cursor state、User session data 信息会放到 LARGE POOL 中,如果 LARGE_POOL_SIZE 没有设置,就会放到 SHARE POOL 这将会使 SHARE POOL 产生碎片,影响性能。


6.一些相关动态视图:
    V$CIRCUIT
    V$SHARED_SERVER
    V$DISPATCHER
    V$SHARED_SERVER_MONITOR
    V$QUEUE
    V$SESSION

例子:查看使用哪种方式连接数据库



SQL> select sid from v$mystat where rownum=1;


       SID
----------
         9


SQL> select server from v$session
  2  where sid=9;


SERVER
---------
SHARED



7.查看 listener 信息:
    使用 Shared Server 时,当 Instance 启动时,PMON 会动态将 service_names 参数,或 DISPATCHERS 中的 SERVICE 参数设定的值邦定到 LISTENER,并为该 SERVICE 分配相应的 DISPATCHER,这些信息可以通过 LSNRCTL 命令来获得:



C:\Documents and Settings\Administrator>lsnrctl


LSNRCTL for 32-bit Windows: Version 9.2.0.3.0 - Production on 17-MAY-2006 23:22:58


Copyright (c) 1991, 2002, Oracle Corporation.  All rights reserved.


Welcome to LSNRCTL, type "help" for information.


LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=heysky)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for 32-bit Windows: Version 9.2.0.3.0 - Produc
tion
Start Date                17-MAY-2006 21:41:12
Uptime                    0 days 1 hr. 46 min. 13 sec
Trace Level               off
Security                  OFF
SNMP                      OFF
Listener Parameter File   E:\oracle\ora92\network\admin\listener.ora
Listener Log File         E:\oracle\ora92\network\log\listener.log
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=heysky)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC0ipc)))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
  Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Service "SKYSHARED.heysky.net" has 1 instance(s).
  Instance "sky", status READY, has 4 handler(s) for this service...
Service "SKYTEST" has 1 instance(s).
  Instance "SKY", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
LSNRCTL> service
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=heysky)(PORT=1521)))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
  Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0
         LOCAL SERVER
Service "SKYSHARED.heysky.net" has 1 instance(s).
  Instance "sky", status READY, has 4 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
      "D002" established:0 refused:0 current:0 max:1002 state:ready
         DISPATCHER <machine: HEYSKY, pid: 3600>
         (ADDRESS=(PROTOCOL=tcp)(HOST=heysky)(PORT=2312))
      "D001" established:0 refused:0 current:0 max:1002 state:ready
         DISPATCHER <machine: HEYSKY, pid: 2748>
         (ADDRESS=(PROTOCOL=tcp)(HOST=heysky)(PORT=2311))
      "D000" established:0 refused:0 current:0 max:1002 state:ready
         DISPATCHER <machine: HEYSKY, pid: 684>
         (ADDRESS=(PROTOCOL=tcp)(HOST=heysky)(PORT=2309))
Service "SKYTEST" has 1 instance(s).
  Instance "SKY", status UNKNOWN, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0
         LOCAL SERVER
The command completed successfully


    如果 LISTENER 启动,数据库的任何动态改变,比如,DISPATCHERS、SERVICE_NAMES 都会动态邦定到 LISTENER,从 LSNRCTL 可以看到这些改变,如果 LISTENER 没有启动,改变之后,再启动 LISTENER,那么这些改变不会邦定到 LISTENER 上。所以一般建议,先启动 LISTENER,再启动数据库,以便能够动态邦定。