首页 | 摘要显示 | 上一页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下一页

DBA Archives

July 23, 2007

open resetlogs何时成了第一招? 唯一一招?

    今天在QQ上遇这样一件事情, 大约是这样的. 一个运行在Linux上的Oracle数据库, 在正常关闭数据库后, 将磁盘从一台机器挂到另一台机器后, 磁盘的顺序发生了变化, 比如/dev/sdb变成了/dev/sdc, /dev/sdc变成了/dev/sdb, 由于这是在正常关闭数据库的情况下做的, 因此只要准确地改变软链接的映射关系(用了磁盘分区方式的裸设备), 是完全可以正常打开的, 结果一个负责安装RAC的公司, 应当是在没有完全搞对映射关系时, 直接进行了open resetlogs操作. 当然这时是启不来的了.

    接下来, 多次open resetlogs失败之后, 用了一个旧的system文件的备份(用dd备份出来的), 再dd回去了, 拷回去后才知道, 因为磁盘空间的问题, 所有的归档日志文件已经被另一队人员干掉了. 最后我让他查了一下v$datafile中的checkpoint_scn#一列, 发现有两个文件的scn号非常小, 从文件名称来看一个是索引一个是数据表空间的, 不知道他们做了什么, 是不是混乱地进行了dd in和dd out了.

    于是我问他是不是有数据库的备份, 他说有, 不过没有拷Redo和Undo文件, 以为它们不重要. 如果这些文件是在错误的open resetlogs之前备份的, 那么数据库肯定是可以直接open的, 只要将undo文件offline drop掉, 并且清一下当前日志组, 结果他说他不知道是在open resetlogs之前的, 还是之后的, 遇到这种程度的人, 真不知道能不能拷对文件, dd可是比较复杂的程序. 晕啊.

    在整个事件中, 我想最严重的是第一次的open resetlogs了, 不知道从哪儿学来的, 如果数据库打不开就进行open resetlogs, 真是一个很坏的习惯.

August 2, 2007

如何取得Oracle当前会话的编号(Session ID)?

    下面这个应当是大家常用的.

SQL> SELECT SID FROM V$MYSTAT WHERE ROWNUM =1;

       SID
----------
     19949

    下面一个更简单, 但只能在Oracle 10g及以上版本中使用.

SQL> SELECT USERENV('SID') FROM DUAL;

USERENV('SID')
--------------
         19949

    下面这个方法我有时也用, 因为不想用最上面的SQL去写一个子查询, 发现在Oracle 9i上很正常, 但在Oracle 10g上常常返回两行, 因此不能再使用它了.

SQL> SELECT SID FROM V$SESSION WHERE AUDSID=USERENV('SESSIONID');

       SID
----------
     19949
     19829

    孔乙己可以写八种茴字, 我已会三种了.

August 8, 2007

Internal error: ulconnect: OCIInitialize [1804]

    一个用sqlldr来装载数据的批处理角本发生了如上错误.

% 9205/bin/sqlldr *****/*****@***** control=testsqlldr.ctl data=.....

SQL*Loader: Release 9.2.0.5.0 - Production on Tue Aug 7 18:00:35 2007

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

SQL*Loader-704: Internal error: ulconnect: OCIInitialize [1804]

    一开始我以为1804就是ORA-01804, 于是就用oerr查错误信息.

01804, 00000, "failure to initialize timezone information"
// *Cause: The timezone information file was not properly read.
// *Action: Please contact Oracle Customer Support.

    但经过检查没有什么Timestamp类型的列啊? 而且单独运行是可以的. 几经周折, 最后发现在程序中指定了使用9205的sqlldr, 而Shell登录进去时设的环境变量还是8174的. 检查一下环境变量设置.

% env | grep ORACLE_HOME
ORACLE_HOME=/export/home/oracle/products/8174x64

    为什么他们要作这个变动呢? 因为他们想用Direct Load, 其实Direct Load要求sqlldr的版本和数据库的版本一致, 因此9203的客户端也是不行的, 还是改回8174的吧, 通过加大BINDSIZE和READSIZE来优化sqlldr的速度算了.

August 9, 2007

SQL*Plus出现段错误及Core dump

    当你的SQL语句很长(估计是2048个字节)并写成一行时, 用SQL*Plus去运行这个角本时, 就会出现这个错误. 原因是SQL*Plus中用一个有最大行长度限制的单行缓冲区去读取一行, 当读到的一行比这个单行缓冲区长时就出问题, 整成多行就没有问题. 每读入一行就将这一行的SQL拼接到更大的(如64K)SQL缓冲区中.

    这种Overflow的方法就是一开始黑客用的攻击手段, 想出来的对册是在内核的代码及程序中, 一律改成有长度限制的函数调用, 这样一改后, 通过这种方法攻击的成功率就降低很多了.

    遇到这个问题后, 突然记起我的AUL/MyDUL工具也遇到过, 它的行缓冲区是1024, 当时有一个外国人去恢复表时, 因为表的定段太多了, 在指定列的类型后, 这个UNLOAD命令长得刚好超出了1024个字节, 也是想了好久才想到的. 后来建议将一行折成两行就没事了.

    正在手工将这个SQL折成多行运行呢!

ORA-30175: invalid type given for an argument

    今天朋友遇到一个比较郁闷的问题, 想了一段时间还没有想出来, 于是在网上问我. 下面这一段代码报了这个错误:

declare
   l_max_date VARCHAR2 (50) := '2999-12-31 23:59:59';
   l_format   VARCHAR2 (50) := 'YYYY-MM-DD HH24:MI:SS';
begin
  INSERT INTO ...
  SELECT ....  FROM tab1@link1 A, tab2@link2 B
  WHERE join_condition
    AND A.COL1 > TO_DATE (l_max_date, l_format);
end;
/

    我在本机上试了是好的啊. 于是我就说我试的版本是10g的, 他说他的是9208的, 于是第一个想法就是Bug了? 正常我们将要一致同意遇到Bug时, 朋友检查了一个远程表的列类型, 发现A.COL1的类型是TIMESTAMP WITH TIME ZONE, 最后改了变量类型就好了.

    我们还真不能随便怀疑Oracle, 那怕是遇到一些让你很不理解的现象, 有可能是你错了或漏了什么地方, 仔细检查一下.

上一页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下一页

当前分类: DBA

Creative Commons License
本站版权: 共用创作 CC
署名-非商业性-相同方式分享
本站基于MT-3.36免费版
(©)版权所有, 2004 - 2008, www.AnySQL.net, 保留所有权利.
MSN: loufangxin(a)msn.com, Mail: anysql(at)126.com/support(at)iamdba.com, Skype ID:anysql