#
測試控制全局死鎖的隱含參數_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比如所有等待事件的描述。