#
测试控制全局死锁的隐含参数_lm_dd_interval时,突然想到这个问题。
RAC全局死锁检测时间:http://yangtingkun.net/?p=955
Oracle的死锁判断是没有优先级的,也就是说,当两个或多个会话发生死锁的时候,无法指定牺牲哪个会话,而是由Oracle随机决定。
不过对于RAC环境而言,死锁的检查不在是内部的随机实现,Oracle通过隐含参数_lm_dd_interval来控制死锁的检测时间。更重要的是,对于RAC环境而言,Oracle允许不同实例设置不同的值。而不同实例的检测死锁间隔不同,就意味着优先级的出现。
如果实例1上设置该值为默认值60秒,而实例2设置为30秒,那么当发生死锁后,永远是实例2上先检测到死锁,也就是说,实例2上会话会被牺牲掉。
这是两个实例上设置该参数相同的情况,两个会话分别连接到两个实例,产生死锁。实例1上的会话1:
SQL> select name from v$database;
NAME
---------
ORCL
SQL> select instance_number, instance_name from v$instance;
INSTANCE_NUMBER INSTANCE_NAME
--------------- ----------------
1 orcl1
SQL> set sqlp 'I1S1> '
I1S1> show parameter _lm
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_lm_dd_interval integer 30
I1S1> set timing on
I1S1> update t_deadlock set name = 'a1' where id = 1;
1 row updated.
Elapsed: 00:00:00.07
在实例2上连接会话2:
SQL> select name from v$database;
NAME
---------
ORCL
SQL> select instance_number, instance_name from v$instance;
INSTANCE_NUMBER INSTANCE_NAME
--------------- ----------------
2 orcl2
SQL> set sqlp 'I2S2> '
I2S2> show parameter _lm
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_lm_dd_interval integer 30
I2S2> set timing on
I2S2> update t_deadlock set name = 'b2' where id = 2;
1 row updated.
Elapsed: 00:00:00.04
I2S2> update t_deadlock set name = 'a2' where id = 1;
会话1上锁定记录2,产生死锁:
I1S1> update t_deadlock set name = 'b1' where id = 2;
第一次是实例2上的会话2被牺牲报错:
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:32.15
I2S2> update t_deadlock set name = 'a2' where id = 1;
可以看到,会话2等待30秒后报错,此时会话2执行同样的语句再次引发死锁:
update t_deadlock set name = 'b1' where id = 2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:01:00.39
I1S1> update t_deadlock set name = 'b1' where id = 2;
这次变成实例1上的会话1被牺牲报错,可以看到tb,会话1经历了两次死锁检测,因此执行时间为1分钟。会话1再次引入死锁:
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:01:01.69
I2S2>
被牺牲的又变成了会话2。
上面这个测试是在两个实例的_lm_dd_interval参数设置相同的情况下,下面修改实例2上的参数设置为5秒:
I2S2> alter system set "_lm_dd_interval" = 5 scope = spfile sid = 'orcl2';
System altered.
Elapsed: 00:00:00.09
I2S2> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
I2S2> startup
ORACLE instance started.
Total System Global Area 281018368 bytes
Fixed Size 2095672 bytes
Variable Size 121636296 bytes
Database Buffers 150994944 bytes
Redo Buffers 6291456 bytes
Database mounted.
Database opened.
I2S2> show parameter _lm
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_lm_dd_interval integer 5
I2S2> update t_deadlock set name = 'b2' where id = 2;
1 row updated.
Elapsed: 00:00:00.06
实例2参数生效后连接会话更新该表,实例1上的会话1取消之前的修改,重新进行更新:
1 row updated.
Elapsed: 00:10:08.98
I1S1> rollback;
Rollback complete.
Elapsed: 00:00:00.00
I1S1> update t_deadlock set name = 'a1' where id = 1;
1 row updated.
Elapsed: 00:00:00.01
I1S1> update t_deadlock set name = 'b1' where id = 2;
下面在实例2上的会话2,引入死锁:
I2S2> update t_deadlock set name = 'a2' where id = 1;
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:06.07
I2S2> update t_deadlock set name = 'a2' where id = 1;
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:05.95
I2S2> update t_deadlock set name = 'a2' where id = 1;
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:06.63
I2S2> update t_deadlock set name = 'a2' where id = 1;
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:05.89
显然由于不同实例的_lm_dd_interval参数的值设置不同,现在每次死锁都会在设置值更小的实例2上被检测,实例2上的会话每次都会被死锁牺牲掉。尝试设置不同的参数值在不同实例上设置死锁检测优先级获得成功。
从这篇文档中学到了不少语法和功能。
虽然对于TYPE以及COLLECTION类型经常使用,但是涉及到把这些类型作为表的存储结构接触的就少多了,而如果说在加上继承等告警特性,平常使用的就更少了。
在Oracle使用对象一般而言是为了简化某些工作,而把所有面向对象的语法和功能都搬到数据库中不太现实,而且一旦TYPE被应用到表结构中,就很难再进行改变,因此数据库中使用TYPE有一定的局限性。
不过对于一些语法和功能还是有必要知道的,TB或者至少在碰到问题时,应该知道查看那篇文档。
一直认为Oracle对于所有分区的操作都是一样的,只有数据的改变才会导致分区状态的失效,没想到HASH分区的实现方式并不相同。
HASH分区表增加新的分区的一点研究:
看一个范围分区SPLIT的例子:
SQL> CREATE TABLE T_PART
2 (ID NUMBER, NAME VARCHAR2(30))
3 PARTITION BY RANGE (ID)
4 (PARTITION P1 VALUES LESS THAN (10),
5 PARTITION PMAX VALUES LESS THAN (MAXVALUE));
Table created.
SQL> INSERT INTO T_PART
2 SELECT ROWNUM, TNAME
3 FROM TAB;
12 rows created.
SQL> CREATE INDEX IND_T_PART_ID ON T_PART(ID) LOCAL;
Index created.tb
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_PART_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_PART_ID P1 USABLE
IND_T_PART_ID PMAX USABLE
SQL> SELECT COUNT(*) FROM T_PART PARTITION (PMAX);
COUNT(*)
----------
3
SQL> ALTER TABLE T_PART SPLIT PARTITION PMAX AT (20)
2 INTO (PARTITION P2, PARTITION P3);
Table altered.
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_PART_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_PART_ID P2 USABLE
IND_T_PART_ID P3 USABLE
IND_T_PART_ID P1 USABLE
可以看到,对于范围分区而言,即使是SPLIT包含数据的分区,只要没有真正导致数据发生变化,就不会导致索引的失效。这里将PMAX分区SPLIT成P2和P3两个分区,其中PMAX中的所有数据都进入P2分区,而P3分区为空,这种情况下没有数据的改变,因此所有分区索引的状态都不会变为UNUSABLE。
但是HASH分区的ADD PARTITION并没有遵守这个规则,事实上对于每次ADD分区,都会导致一个分区的数据发生分裂,而分裂的结果不管原分区的数据是否发生变化,都会导致原分区索引状态变为UNUSABLE,至于新增分区的索引状态,则取决于是否有数据的改变。
SQL> CREATE TABLE T_HASH
2 (ID NUMBER)
3 PARTITION BY HASH (ID)
4 (PARTITION P1,
5 PARTITION P2,
6 PARTITION P3,
7 PARTITION P4);
Table created.
SQL> CREATE INDEX IND_T_HASH_ID ON T_HASH(ID) LOCAL;
Index created.
SQL> INSERT INTO T_HASH SELECT ROWNUM FROM TAB;
12 rows created.
SQL> COMMIT;
Commit complete.
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_HASH_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_HASH_ID P1 USABLE
IND_T_HASH_ID P2 USABLE
IND_T_HASH_ID P3 USABLE
IND_T_HASH_ID P4 USABLE
SQL> SELECT * FROM T_HASH PARTITION (P1);
ID
----------
6
11
SQL> SELECT * FROM T_HASH PARTITION (P2);
ID
----------
9
10
12
SQL> SELECT * FROM T_HASH PARTITION (P3);
ID
----------
2
5
8
SQL> SELECT * FROM T_HASH PARTITION (P4);
ID
----------
1
3
4
7
下面新增一个PARTITION P5:
SQL> ALTER TABLE T_HASH ADD PARTITION P5;
Table altered.
SQL> SELECT * FROM T_HASH PARTITION (P5);
no rows selected
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_HASH_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_HASH_ID P5 USABLE
IND_T_HASH_ID P1 UNUSABLE
IND_T_HASH_ID P2 USABLE
IND_T_HASH_ID P3 USABLE
IND_T_HASH_ID P4 USABLE
新增的PARTITION P5中并没有任何的数据,也就是说没有任何的数据从P1迁移到P5中,但是查询分区索引的状态发现,P1对应的分区索引状态已经变为UNUSABLE。这和范围分区的处理方式完全不同。而P5分区由于没有任何数据,因此分区状态是USABLE。
SQL> ALTER TABLE T_HASH ADD PARTITION P6;
Table altered.
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_HASH_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_HASH_ID P5 USABLE
IND_T_HASH_ID P6 UNUSABLE
IND_T_HASH_ID P1 UNUSABLE
IND_T_HASH_ID P2 UNUSABLE
IND_T_HASH_ID P3 USABLE
IND_T_HASH_ID P4 USABLE
6 rows selected.
SQL> DELETE T_HASH WHERE ID = 5;
1 row deleted.
SQL> COMMIT;
Commit complete.
SQL> ALTER TABLE T_HASH ADD PARTITION P7;
Table altered.
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_HASH_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_HASH_ID P5 USABLE
IND_T_HASH_ID P6 UNUSABLE
IND_T_HASH_ID P7 UNUSABLE
IND_T_HASH_ID P1 UNUSABLE
IND_T_HASH_ID P2 UNUSABLE
IND_T_HASH_ID P3 UNUSABLE
IND_T_HASH_ID P4 USABLE
7 rows selected.
SQL> SELECT * FROM T_HASH PARTITION (P3);
no rows selected
SQL> SELECT * FROM T_HASH PARTITION (P7);
ID
----------
2
8
为了更好的说明这个问题,在增加PARTITION P7之前,删除了ID为5的记录,这是增加分区后可以发现,原有的P3已经不包含任何的数据,全部的记录都进入到新增的P7分区,但是无论是P3还是P7,状态都是UNUSABLE。这证明了前面提到的,只要是新增HASH分区,就会导致源分区索引状态变为UNUSABLE,除非是一种情况:源分区本身就没有数据:
SQL> ALTER TABLE T_HASH ADD PARTITION P8;
Table altered.
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
2 FROM USER_IND_PARTITIONS
3 WHERE INDEX_NAME = 'IND_T_HASH_ID';
INDEX_NAME PARTITION_NAME STATUS
------------------------------ ------------------------------ --------
IND_T_HASH_ID P5 USABLE
IND_T_HASH_ID P6 UNUSABLE
IND_T_HASH_ID P7 UNUSABLE
IND_T_HASH_ID P1 UNUSABLE
IND_T_HASH_ID P2 UNUSABLE
IND_T_HASH_ID P3 UNUSABLE
IND_T_HASH_ID P4 USABLE
IND_T_HASH_ID P8 USABLE
8 rows selected.
事实上,对于HASH分区的ADD PARTITION操作,Oracle基本上还是秉承了没有数据变化就不会导致索引失效的思路。唯一的差别在于,对于源分区包含记录的情况,Oracle并没有最后去验证,是否真的发生了数据的迁移。
今天是ACOUG活动的日子,也是上半年的最后一天。
参加ACOUG的人很多,现场估计超过了100人,而且今天到会的ACE也很多,除了tbEygle、Kamus、崔华和刚晋升为ACE的侯圣文之外,还有从成都赶过来的老熊。老熊虽然是第一次见面,此前打交道的次数也不多,但是有种一见如故的感觉,可能和老熊直爽的性格有关。
今天的第一个主题是杨海朝带来的《MySql的那点事儿》。杨海朝是新浪的首席DBA负责新浪微博的后台数据库,他带来的MySql方面的演讲介绍了如何利用mysql处理海量增长的大数据,以及如何满足前端应用的高可用需求。
第二个是Kamus带来的11g新特性。在10g已经推出了正常服务期,12c马上就要推出的今天,仍然有很多DBA对于11g的新特性不是很了解。Kamus的演讲应该算是一个新特性的普及,这次的内容是关于分区和高可用特性方面的新特性。
最后是崔华带来的SQL优化方面的主题,这次的内容是统计信息。崔华的演讲贯彻了他一向的风格,包含了大量的深入信息,并给出了很多Oracle内部算法和公式,而这些公式大部分来自他深入的研究,在其他的地方是无法看到的。
对于单实例数据库而言,死锁的检测在秒级完成,而RAC环境则死锁的检测时间默认达到了1分钟。
对于单实例环境如果出现了死锁,那么马上其中一个进程就被中止,用户可以快速的得到错误返回。而对于RAC而言,死锁的检测并不是实时完成,而是需要60秒左右的时间。
会话1执行:
SQL> create table t_deadlock (id number primary key, name varchar2(30));
Table created.
Elapsed: 00:00:00.12
SQL> insert into t_deadlock values (1, 'a');
1 row created.
Elapsed: 00:00:00.00
SQL> insert into t_deadlock values (2, 'b');
1 row created.
Elapsed: 00:00:00.00
SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
SQL> update t_deadlock set name = 'a1' where id = 1;
1 row updated.
Elapsed: 00:00:00.00
会话2执行:
SQL> set timing on
SQL> update t_deadlock set name = 'b2' where id = 2;
1 row updated.
Elapsed: 00:00:00.00
SQL> update t_deadlock set name = 'a2' where id = 1;
此时,会话2等待会话1的最终操作,下面会话1更新被会话2锁定的行,引发死锁:
SQL> update t_deadlock set name = 'b1' where id = 2;
update t_deadlock set name = 'b1' where id = 2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:01:00.12
可以看到,死锁的超时检测为1分钟。
而这个死锁的检测时间是可以调整的,Oracle通过隐含参数_lm_dd_interval控制:
SQL> conn / as sysdba
Connected.
SQL> alter system set "_lm_dd_interval" = 30 scope = spfile;
System altered.
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 281018368 bytes
Fixed Size 2095672 bytes
Variable Size 104859080 bytes
Database Buffers 167772160 tb bytes
Redo Buffers 6291456 bytes
Database mounted.
Database opened.
再次测试死锁的检测时间,会话1:
SQL> update t_deadlock set name = 'a1' where id = 1;
1 row updated.
SQL> set timing on
会话2执行更新:
SQL> set timing on
SQL> update t_deadlock set name = 'b2' where id = 2;
1 row updated.
Elapsed: 00:00:00.02
SQL> update t_deadlock set name = 'a2' where id = 1;
会话1执行更新引发死锁:
SQL> update t_deadlock set name = 'b1' where id = 2;
大约30秒后,会话2报错ORA-60:
update t_deadlock set name = 'a2' where id = 1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:30.27
在10.2.0.2版本上,Oracle存在一个bug,允许这个参数设置为0,在10.2.0.3以后,这个bug被修正,如果设置为0后,则数据库无法正常启动:
[oracle@node1 ~]$ sqlplus / as sysdba
SQL*Plus: Release 10.2.0.5.0 - Production on Mon Jun 4 07:54:09 2012
Copyright (c) 1982, 2010, Oracle. All Rights Reserved.
Connected to an idle instance.
SQL> startup
ORA-00067: invalid value 0 for parameter _lm_dd_interval; must be at least 1
最后修改隐含参数是Oracle不推荐的,而且修改这个参数势必会影响RAC的正常工作方式导致LDM进程的繁忙度增加,而且可能影响RAC环境的稳定性和可用性。
如果确实对于前台的死锁检查时间要求较高,建议在测试环境中详细测试后再部署到产品环境中。
11g增强了数据泵的NETWORK_LINK功能,使得远端的导入或导出也支持分区粒度。
在10g的时候,数据泵的NETWORK_LINK只支持表粒度:
[orat3@hpserver2 ~]$ expdp test/test network_link=ora10204 dumpfile=tpart.dp logfile=test.log directory=dd tables=t_part:p1
Export: Release 10.2.0.4.0 - 64bit Production on Monday, 4 June, 2012 0:38:31
Copyright (c) 2003, 2007, Oracle. All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORA-39001: invalid argument value
ORA-39203: Partition selection is not supported over a network link.
很明显10g并不支持通过网络方式的分区选择功能。而且对于分区表而言,无论是导出还是导入,都是已一个整体完成的。
而在11g中,无论是导入还是导出,NETWORK_LINK方式都支持分区粒度:
solaris*orcl-/home/oracle$ expdp test/test network_link=t111g dumpfile=t_part_hash.dp directory=d_output nologfile=y tables=t_part_hash:sys_p61
Export: Release 11.2.0.3.0 - Production on Mon Jun 4 08:24:54 2012
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 tb- 64bit Production
With the Partitioning, Oracle Label Security and Real Application Testing options
Starting "TEST"."SYS_EXPORT_TABLE_01": test/******** network_link=t111g dumpfile=t_part_hash.dp directory=d_output nologfile=y tables=t_part_hash:sys_p61
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 8 MB
Processing object type TABLE_EXPORT/TABLE/TABLE
. . exported "TEST"."T_PART_HASH":"SYS_P61" 5.476 KB 13 rows
Master table "TEST"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for TEST.SYS_EXPORT_TABLE_01 is:
/home/oracle/t_part_hash.dp
Job "TEST"."SYS_EXPORT_TABLE_01" successfully completed at 08:25:57
这个功能没有在新特性文档中体现,但是却是一个不错的功能提升。
如果需要了解或架构高可用环境,建议看一下这篇文档。
这篇文档介绍了Oracle高可用相关的知识点,包括ASM、CLUSTER、RAC、DATA GUARD、GOLDENGATE、BACKUP、RESTORE等等,此外还介绍了高可用环境的监控,以及如何利用这些高可用功能来减少维护的停机时间。
从文档的名称高可用最佳实践和文档的页数高,这篇文档中不会包括这些知识点的具体概念,而应该是这些功能在哪些场合使用最合适,以及相互之间如何配合。
照例给出网址:http://www.oracle.com/pls/db112/to_toc?pathname=server.112%2Fe10803%2Ftoc.htm&remark=portal+%28Books%29
客户数据库在SHUTDOWN的过程中执行了取消操作,导致了ORA-600错误。
数据库版本为10.2.0.4 RAC for HP-UX,详细错误信息为:
Thu Oct 22 15:05:14 2009
Shutting down instance: further logons disabled
Thu Oct 22 15:05:15 2009
Stopping background process QMNC
Thu Oct 22 15:05:15 2009
Stopping background process CJQ0
Thu Oct 22 15:05:17 2009
Stopping background process MMNL
Thu Oct 22 15:05:18 2009
Stopping background process MMON
Thu Oct 22 15:05:19 2009
Shutting down instance (immediate)
License high water mark = 8
Thu Oct 22 15:05:19 2009
Stopping Job queue slave processes, flags = 7
Thu Oct 22 15:05:19 2009
Job queue slave processes stopped
Thu Oct 22 15:05:20 2009
ALTER DATABASE CLOSE NORMAL
Thu Oct 22 15:05:20 2009
SMON: disabling tx recovery
SMON: disabling cache recovery tb
Thu Oct 22 15:05:21 2009
LGWR: Waiting for ORLs to be archived...
Thu Oct 22 15:05:36 2009
Reconfiguration started (old inc 2, new inc 4)
List of nodes:
0 1
Global Resource Directory frozen
Communication channels reestablished
* domain 0 valid = 1 according to instance 0
Thu Oct 22 15:05:36 2009
Master broadcasted resource hash value bitmaps
Non-local Process blocks cleaned out
Thu Oct 22 15:05:36 2009
LMS 0: 0 GCS shadows cancelled, 0 closed
Thu Oct 22 15:05:36 2009
LMS 1: 0 GCS shadows cancelled, 0 closed
Set master node info
Submitted all remote-enqueue requests
Dwn-cvts replayed, VALBLKs dubious
All grantable enqueues granted
Thu Oct 22 15:05:36 2009
LMS 1: 2008 GCS shadows traversed, 1001 replayed
Thu Oct 22 15:05:36 2009
LMS 0: 1988 GCS shadows traversed, 1034 replayed
Thu Oct 22 15:05:36 2009
Submitted all GCS remote-cache requests
Fix write in gcs resources
Reconfiguration complete
Thu Oct 22 15:05:51 2009
CLOSE: Error 1013 during database close
Thu Oct 22 15:05:51 2009
SMON: enabling cache recovery
SMON: enabling tx recovery
Thu Oct 22 15:05:51 2009
ORA-1013 signalled during: ALTER DATABASE CLOSE NORMAL...
Thu Oct 22 15:05:51 2009
Errors in file /u01/app/oracle/admin/orcl3/bdump/orcl32_lns1_4678.trc:
ORA-00600: internal error code, arguments: [2658], [4], [2], [], [], [], [], []
Thu Oct 22 15:05:52 2009
Trace dumping is performing id=[cdmp_20091022150552]
Thu Oct 22 15:05:52 2009
Errors in file /u01/app/oracle/admin/orcl3/bdump/orcl32_lns1_4678.trc:
ORA-00600: internal error code, arguments: [2658], [4], [2], [], [], [], [], []
Thu Oct 22 15:05:55 2009
LGWR: ORLs successfully archived
Shutting down archive processes
Archiving is disabled
Thu Oct 22 15:06:00 2009
ARCH shutting down
ARC3: Archival stopped
Thu Oct 22 15:06:05 2009
ARCH shutting down
ARC2: Archival stopped
Thu Oct 22 15:06:10 2009
ARCH shutting down
ARC1: Archival stopped
Thu Oct 22 15:06:15 2009
ARCH shutting down
ARC0: Archival stopped
Thu Oct 22 15:06:16 2009
Thread 2 closed at log sequence 23
Successful close of redo thread 2
可以看到,用户在执行了SHUTDOWN IMMEDIATE操作后,执行了CTRL+C取消操作,导致了ORA-1031错误,之后同一时间引发了ORA-600[2658]错误。显然这个错误的产生和用户发出的取消命令直接相关,而且最终这个命令并未生效,数据库成功的被关闭。
在MOS上查询了一下ORA-600[2658]的相关错误,发现多部分错误都出现在7.3和8.1版本上,在9i以后这个错误已经很少见了,从这一点也可以看出,导致这个错误出现的是偶然的因素,那么取消操作显然是导致这个错误的最大可能性。
数据库本身处于关闭过程中,因此这个错误没有影响,可以直接忽略掉。
两个TIMESTAMP之差得到的是INTERVAL类型,而有时我们只需要得到两个时间相差的秒数,如果变成INTERVAL之后,想要获取这个值会非常麻烦。
比较常见的方法是使用EXTRACT来抽取获得的INTERVAL类型的日、时、分和秒来分别计算并求和:
SQL> create table t_timestamp (id number, t1 timestamp, t2 timestamp);
Table created.
SQL> insert into t_timestamp
2 values (1, to_timestamp('20120603222324', 'yyyymmddhh24miss'), to_timestamp('20120526152354', 'yyyymmddhh24miss'));
1 row created.
SQL> commit;
Commit complete.
SQL> select t1 - t2 from t_timestamp where id = 1;
T1-T2
---------------------------------------------------------------------------
+000000008 06:59:30.000000
SQL> with t as (select t1 - t2 interval from t_timestamp where id = 1)
2 select extract(day from interval) * 86400
3 + extract(hour from interval) * 3600
4 + extract(minute from interval) * 60
5 + extract(second from interval) interval
6 from t;
INTERVAL
----------
716370
对于不需要考虑毫秒的情况而言,这种计算过于麻烦了,而对于DATE类型而言,tb计算差值非常方便,直接就可以返回两个日期相差的天数,在乘以86400就可以得到结果。
可惜的是,无论是ROUND还是TRUNC参数,都不支持TIMESTAMP类型:
SQL> select trunc(t1, 'ss') from t_timestamp where id = 1;
select trunc(t1, 'ss') from t_timestamp where id = 1
*
ERROR at line 1:
ORA-01899: bad precision specifier
SQL> select round(t1, 'ss') from t_timestamp where id = 1;
select round(t1, 'ss') from t_timestamp where id = 1
*
ERROR at line 1:
ORA-01899: bad precision specifier
其实对于这个问题,最简单的方法是利用隐式转换,变成DATE类型的操作:
SQL> select (t1 - 0 - (t2 - 0)) * 86400 from t_timestamp;
(T1-0-(T2-0))*86400
-------------------
716370
当然最标准的方法还是显示的转换:
SQL> select (cast(t1 as date) - cast(t2 as date)) * 86400 from t_timestamp;
(CAST(T1ASDATE)-CAST(T2ASDATE))*86400
-------------------------------------
716370
显然这种方便比利用EXTRACT要简单得多。
一直认为这篇文档作为工具书更合适,不过细读的过程中却改变了我的看法。
之所以这篇文档的优先级放得比较低,和这篇文档的厚度也有关系。不过这1200多页的内容却包含了很多Oracle中最关键的信息。
第一部分就是初始化参数的详细描述,即使这篇文档只包含了这部分内容,也值得一看了。
第二部分是静态数据字典视图,第三部分是动态数据字典视图。这两部分的内容除了作为工具书备查之外,也是补充自己知识全面性的重要文档,Oracle的提供的数据字典覆盖了非常全面的信息,而我们平时只利用了很少的一部分,如果能充分利用这些视图,那么解决问题会更加的轻松。
最后在附录部分还有重要的内容,tb比如所有等待事件的描述。