2009.9.18

バッファ・キャッシュ内に常駐するすべてのセグメントのブロック数をカウント

普段はあまり気にしなくて良いかも知れませんが、
新規のSQLを作る場合や、バッファキャッシュヒット率が悪い
時に調べたりすることがあります。



SQL> r
1 SELECT o.OBJECT_NAME, COUNT(*) NUMBER_OF_BLOCKS
2 FROM DBA_OBJECTS o, V$BH bh
3 WHERE o.DATA_OBJECT_ID = bh.OBJD
4 GROUP BY o.OBJECT_NAME
5* ORDER BY COUNT(*)

OBJECT_NAME                    NUMBER_OF_BLOCKS
------------------------------ ----------------
I_AUX_STATS$                                  1
I_CDEF3                                       1
I_COBJ#                                       1
I_KOPM1                                       1
I_JOB_NEXT                                    1
I_IND1                                        1
I_LINK1                                       1
I_STREAMS_APPLY_PROCESS1                      1
I_TS#                                         1
LOC$                                          1
LINK$                                         1
KOPM$                                         1
JOB$                                          1
I_USER1                                       1
I_USER#                                       1
I_UNDO1                                       1
I_TS1                                         1
UNDO$                                         1
SMON_SCN_TO_TIME_IDX                          1
SMON_SCN_TO_TIME                              1
SMON_SCN_TIME                                 1
SEQ$                                          1
REPCAT$_REPPROP                               1
PENDING_TRANS$                                1
I_STREAMS_CAPTURE_PROCESS1                    1
I_SEQ1                                        1
AQ$_QUEUES                                    2
DAMEDA_DICTIONARY                             2
PROPS$                                        2
MIGRATE$                                      2
TRIGGER$                                      2
ID_GENS$                                      2
INDPART$                                      2
ACCESS$                                       3
DEPENDENCY$                                   3
I_VIEW1                                       3
I_OBJAUTH1                                    3
I_ICOL1                                       3
I_CCOL2                                       3
BOOTSTRAP$                                    4
C_USER#                                       4
TSQ$                                          4
VIEW$                                         4
USER$                                         4
I_ACCESS1                                     5
I_FILE#_BLOCK#                                5
I_DEPENDENCY1                                 6
I_DEPENDENCY2                                 8
CCOL$                                        11
CDEF$                                        11
C_COBJ#                                      11
I_OBJ#                                       12
I_OBJ1                                       15
C_TS#                                        27
FET$                                         27
TS$                                          27
I_OBJ2                                       39
C_FILE#_BLOCK#                               58
SEG$                                         58
UET$                                         58
OBJ$                                         67
ATTRCOL$                                    332
LIBRARY$                                    332
VIEWTRCOL$                                  332
TYPE_MISC$                                  332
TAB$                                        332
SUBCOLTYPE$                                 332
REFCON$                                     332
OPQTYPE$                                    332
NTAB$                                       332
LOB$                                        332
ICOL$                                       332
IND$                                        332
ICOLDEP$                                    332
CLU$                                        332
C_OBJ#                                      332
COL$                                        332
COLTYPE$                                    332

78行が選択されました。

バッファキャッシュにのっているセグメントのブロック数がわかるので、
SQLがどの程度バッファを使用するかなどわかるので便利です。

2009.9.17

set timing on time on のススメ

SQL*PLUSのSETコマンドです。

実行したSQLがどのくらいの時間で終わるかは、勘と経験を積むしかありません。
ログに時刻や実行時間を出力させておくと、前回やった内容はどれくらいで終わっ
てたかわかるので、便利(というか、イチイチ試験して調べ直すより楽&確実)です。



Microsoft Windows [Version 6.0.6001]
Copyright (c) 2006 Microsoft Corporation. All rights reserved.

C:\Windows\system32>sqlplus / as sysdba

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 17 23:21:37 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
に接続されました。
SQL> set timing on time on

23:22:50 SQL> truncate table index_test;

表が切り捨てられました。

経過: 00:00:01.06
23:23:09 SQL> insert into index_test select to_char(level),to_char(level*10) from dual connect by level <= 20000;

20000行が作成されました。

経過: 00:00:00.43
23:23:16 SQL>

「set timing on」は実行時間が出力されます。
「set time on」は時刻が出力されます。

2009.9.16

インデックスのダンプ

インデックスのダンプをとってみます。

まずは、テーブルとインデックスを作成します。



SQL> create table index_test (
2 column1 char(10) primary key,
3 column2 char(10)
4 )
5 tablespace USERS;

表が作成されました。

SQL> create index index_test_ind on index_test ( column2 );

索引が作成されました。

SQL> select index_name from dba_indexes where table_name = 'INDEX_TEST';

INDEX_NAME
------------------------------------------------------------
SYS_C004127
INDEX_TEST_IND

ゼロ件でINDEXのダンプをとってみます。



SQL> select object_id from user_objects where object_name in ('SYS_C004127','INDEX_TEST_IND');

OBJECT_ID
----------
14088
14087

SQL> alter session set events 'immediate trace name treedump level 14088:immediate trace name treedump level 14087';

セッションが変更されました。

※eventを複数設定するときは区切り文字を「:」にします。他にもあるらしいのですが、それはまた今度。

ユーザトレースファイルの出力先(USER_DUMP_DESTパラメータ)にファイルが出力されます。



----- begin tree dump
leaf: 0x40a782 4237186 (0: nrow: 0 rrow: 0)
----- end tree dump
----- begin tree dump
leaf: 0x1001f94 16785300 (0: nrow: 0 rrow: 0)
----- end tree dump

ゼロ件の場合はこんな感じです。

2件のデータを追加してみます。



SQL> insert into index_test select to_char(level),to_char(level*10) from dual connect by level commit;

コミットが完了しました。

また、ダンプしてみます。



SQL> alter session set events 'immediate trace name treedump level 14088:immediate trace name treedump level 14087';

セッションが変更されました。

今度はこうなりました。



*** 2009-09-16 23:14:15.778
----- begin tree dump
leaf: 0x40a782 4237186 (0: nrow: 2 rrow: 2)
----- end tree dump
----- begin tree dump
leaf: 0x1001f94 16785300 (0: nrow: 2 rrow: 2)
----- end tree dump

こんどは1件削除してみます。



SQL> delete from index_test where rownum = 1
2 ;

1行が削除されました。

SQL> commit;

コミットが完了しました。

またまた、ダンプしてみます。



SQL> alter session set events 'immediate trace name treedump level 14088:immediate trace name treedump level 14087';

セッションが変更されました。

こんな感じになりました。



*** 2009-09-16 23:16:19.908
----- begin tree dump
leaf: 0x40a782 4237186 (0: nrow: 2 rrow: 1)
----- end tree dump
----- begin tree dump
leaf: 0x1001f94 16785300 (0: nrow: 2 rrow: 1)
----- end tree dump

内容から判断すると「nrow」は2件のレコードがインデックスのリーフブロックに
格納されていて、「rrow」は1件が有効なレコードになっているということ。

※ダンプをみるとリーフ分割が過剰に発生していたり、虫食いになっていたりして
いることが多分わかるんじゃないかなと思います。rebuildをすると、きっとnrowが1になります。



SQL> alter index SYS_C004127 rebuild;

索引が変更されました。

SQL> alter index INDEX_TEST_IND rebuild;

索引が変更されました。

SQL> select object_id,data_object_id from user_objects where object_name in ('SYS_C004127','INDEX_TE
ST_IND');

OBJECT_ID DATA_OBJECT_ID
---------- --------------
14088 14090
14087 14089

SQL> alter session set events 'immediate trace name treedump level 14088:immediate trace name treedump level 14087';

セッションが変更されました。

*** 2009-09-16 23:24:39.672
----- begin tree dump
leaf: 0x40a80a 4237322 (0: nrow: 1 rrow: 1)
----- end tree dump
----- begin tree dump
leaf: 0x1001f9c 16785308 (0: nrow: 1 rrow: 1)
----- end tree dump

予想通りの結果になりました。

2009.9.13

leaf node split

v$sysstatに「leaf node split」というイベントがあったので、少し調べてみました。

Oracleだとsplitというキーワードは、インデックスのリーフ分割のことを指しているようです。
インデックスがB*tree構造になっていて、一番上がroot(根)、その下がbranch(枝)最下層がleaf(葉)と
呼ばれているので、leafはインデックスの最下層のブロック(テーブルに格納されている行のrowidを持っている
ところ)のことを指してします。



SQL> column name for A25
SQL> r
1* select name,value from v$sysstat where name like '%split%'

NAME VALUE
------------------------- ----------
leaf node splits 0
leaf node 90-10 splits 0
branch node splits 0
queue splits 0

SQL> create table SPLIT_TEST
2 (
3 i number(10) primary key,
4 name char(10)
5 );

表が作成されました。

SQL> insert into SPLIT_TEST
2 select level*5000,'TEST' from dual connect by level commit;

コミットが完了しました。

SQL> select name,value from v$sysstat where name like '%split%';

NAME VALUE
------------------------- ----------
leaf node splits 18
leaf node 90-10 splits 18
branch node splits 0
queue splits 0

SQL> insert into SPLIT_TEST
2 select level,'TEST' from dual connect by level commit;

コミットが完了しました。

SQL> select name,value from v$sysstat where name like '%split%';

NAME VALUE
------------------------- ----------
leaf node splits 36
leaf node 90-10 splits 18
branch node splits 0
queue splits 0

初回にインデックス順(連番)にデータを追加すると「leaf node 90-10 splits」と「leaf node splits」が
同じ値になりました。こんどは、5000ごとに増加していた値を1ずつ4999までに変更してデータを追加する
と既に存在しているleafブロックを分割しながらデータを追加しているため、「leaf node splits」のみ値が
増えています。「leaf node splits」はリーフ分割が起こったイベントをカウントしているみたいです。

「leaf node 90-10 splits」は新規にブロックを追加するイメージになっているよう。

※主キー(索引とかも同じ)を作成する場合



SQL> ALTER TABLE SPLIT_TEST DROP PRIMARY KEY CASCADE DROP INDEX;

表が変更されました。

SQL> shutdown immediate;
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SQL> startup
ORACLEインスタンスが起動しました。

Total System Global Area 134217728 bytes
Fixed Size 1286148 bytes
Variable Size 83890172 bytes
Database Buffers 46137344 bytes
Redo Buffers 2904064 bytes
データベースがマウントされました。
データベースがオープンされました。
SQL>
SQL> select name,value from v$sysstat where name like '%split%';

NAME VALUE
------------------------- ----------
leaf node splits 0
leaf node 90-10 splits 0
branch node splits 0
queue splits 0

SQL> ALTER TABLE SPLIT_TEST ADD CONSTRAINT SPLIT_TEST_PKEY PRIMARY KEY(i);

表が変更されました。

SQL> select name,value from v$sysstat where name like '%split%';

NAME VALUE
------------------------- ----------
leaf node splits 0
leaf node 90-10 splits 0
branch node splits 0
queue splits 0

インデックスを作成する場合はカウントされていませんでした。

2009.9.11

SQLが解析されたときのオプティマイザ統計をDUMPする

OracleDatabaseのSQL実行プランを見ていると、「なんでHASH_JOINになる?」といった
ことがたまにあったりします。どういう判断をしているかを知りたい場合は、DUMPをとると
わかるかも知れません。


SQL> alter session set events '10053 trace name context forever , level 4';

セッションが変更されました。

SQL> alter system flush shared_pool;

システムが変更されました。

SQL> alter system flush buffer_cache;

システムが変更されました。

SQL> select count(*) from dameda where empno = 10000010;

COUNT(*)
----------
1

SQL> select count(*) from dameda where empno between 10000010 and 11000000;

COUNT(*)
----------
100000

ダンプしたトレースファイルは「user_dump_dest」初期化パラメータに設定したフォルダに
出力されます。

ファイルには以下の内容(一部)が出力されています。

***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: DAMEDA Alias: DAMEDA
#Rows: 100000 #Blks: 622 AvgRowLen: 35.00
Index Stats::
Index: DAME Col#: 2 3
LVLS: 2 #LB: 575 #DK: 8 LB/K: 71.00 DB/K: 68.00 CLUF: 545.00
Index: DAME2 Col#: 4
LVLS: 0 #LB: 0 #DK: 0 LB/K: 0.00 DB/K: 0.00 CLUF: 0.00
***************************************
SINGLE TABLE ACCESS PATH
Column (#1): EMPNO(NUMBER)
AvgLen: 6.00 NDV: 100000 Nulls: 0 Density: 1.0000e-005 Min: 10000050 Max: 10999650
Using prorated density: 9.9996e-006 of col #1 as selectivity of out-of-range value pred
Table: DAMEDA Alias: DAMEDA
Card: Original: 100000 Rounded: 1 Computed: 1.00 Non Adjusted: 1.00
Access Path: TableScan
Cost: 174.07 Resp: 174.07 Degree: 0
Cost_io: 170.00 Cost_cpu: 24429536
Resp_io: 170.00 Resp_cpu: 24429536
Best:: AccessPath: TableScan
Cost: 174.07 Degree: 1 Resp: 174.07 Card: 1.00 Bytes: 0

sql_id=61aknt7qf4n04.
Current SQL statement for this session:
select count(*) from dameda where empno = 10000010

============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id  | Operation           | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |         |       |      |   174 |           |
| 1   |  SORT AGGREGATE      |         |     1 |     6 |       |           |
| 2   |   TABLE ACCESS FULL | DAMEDA  |     1 |     6 |   174 | 00:00:03 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter("EMPNO"=10000010)

上記の例では、10万件のうちから1件を取り出すのに、インデックスを使わないでテーブルスキャン
をしたほうが良いと判断しているみたいです。






2009.9.10

リスナー(listener)の接続エラーの確認

クライアントとサーバ間のネットワーク経由の接続は「Oracle Net Services」を
利用します。リスナーはクライアントからの接続要求に対して、サーバプロセスを
立ち上げて接続を確立してくれるプロセスです。リスナーは接続完了後は通信
には関与しません。リスナー経由の代表的なエラーパターンを実際に試してみ
ました。

0.正常時


C:\Windows\system32>sqlplus system/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)^
More? (HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orcl)))

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:27:40 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
に接続されました。
SQL>

1.接続先ホストが見つからない


C:\Windows\system32>sqlplus system/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)^
More? (HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orcl)))

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:19:24 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12170: TNS: 接続タイムアウトが発生しました。

2.リスナーに接続できない


C:\Windows\system32>sqlplus system/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)^
More? (HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orcl)))

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:31:53 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12541: TNS: リスナーがありません。

3.接続ポートが違う


C:\Windows\system32>sqlplus system/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)^
More? (HOST=10.168.1.100)(PORT=1522)))(CONNECT_DATA=(SID=orcl)))

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:36:20 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12541: TNS: リスナーがありません。

4.SIDが違う


C:\Windows\system32>sqlplus system/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)^
More? (HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orclxxx)))

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:37:18 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12505: TNS: リスナーは接続記述子で指定されたSIDを現在認識していません

5.インスタンスが停止中


C:\Windows\system32>sqlplus system/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)^
More? (HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orcl)))

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:39:39 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12505: TNS: リスナーは接続記述子で指定されたSIDを現在認識していません

6.tnsnames.oraに無い識別子を使用している


C:\Windows\system32>sqlplus system/oracle@XE2

SQL*Plus: Release 10.2.0.1.0 - Production on 木 9月 10 22:51:18 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

2009.9.9

begin backup と end backup

アーカイブログ運用をしている場合は、データベースを
起動したままでバックアップを取得できます。
OSコマンドやストレージ連携製品のコマンドでバックアップ
を取得する場合は、バックアップ前に
「alter database begin backup」もしくは「alter tablespace [表領域名] begin backup」
コマンドを実行してからOSコマンド(ファイルコピー)などで
データファイルのバックアップを取得します。

今回はよくある運用ミスを再現します。
データベースのオンラインバックアップを取得する時に「begin backup」
を実行するが、「end backup」をし忘れてデータベースを停止してしまい
データベースが起動しなくなってしまった。


C:\Windows\system32>sqlplus / as sysdba

SQL*Plus: Release 10.2.0.1.0 - Production on 水 8月 26 22:11:02 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
に接続されました。
SQL> archive log list
データベース・ログ・モード アーカイブ・モード
自動アーカイブ 有効
アーカイブ先 USE_DB_RECOVERY_FILE_DEST
最も古いオンライン・ログ順序 2
アーカイブする次のログ順序 3
現行のログ順序 3
SQL>
SQL> alter database begin backup;

データベースが変更されました。

SQL> set pagesize 1000
SQL> select * from v$backup where status = 'ACTIVE';

FILE# STATUS CHANGE# TIME
---------- ------------------------------------ ---------- --------
1 ACTIVE 878172 09-08-26
2 ACTIVE 878172 09-08-26
3 ACTIVE 878172 09-08-26
4 ACTIVE 878172 09-08-26

SQL> shutdown immediate;
ORA-01149: シャットダウンできません - ファイル1にオンライン・バックアップが設定されています
ORA-01110: データファイル1: 'D:\ORACLEXE\ORADATA\XE\SYSTEM.DBF'
※通常のshutdownはできませんでした
SQL> shutdown abort;
ORACLEインスタンスがシャットダウンされました。
※クラスタソフトや、管理ツールでは強制的にシャットダウンするやつもいるので注意
SQL>
SQL> startup
ORACLEインスタンスが起動しました。

Total System Global Area 134217728 bytes
Fixed Size 1286148 bytes
Variable Size 83890172 bytes
Database Buffers 46137344 bytes
Redo Buffers 2904064 bytes
データベースがマウントされました。
ORA-01113: ファイル1はメディア・リカバリが必要です
ORA-01110: データファイル1: 'D:\ORACLEXE\ORADATA\XE\SYSTEM.DBF'

SQL> select status from v$instance;

STATUS
------------------------
MOUNTED

SQL> alter database end backup;

データベースが変更されました。
※mountしてend backupすれば起動できるようになります
SQL> shutdown abort;
ORACLEインスタンスがシャットダウンされました。
SQL>
SQL> startup
ORACLEインスタンスが起動しました。

Total System Global Area 134217728 bytes
Fixed Size 1286148 bytes
Variable Size 83890172 bytes
Database Buffers 46137344 bytes
Redo Buffers 2904064 bytes
データベースがマウントされました。
データベースがオープンされました。
SQL>
SQL> select status from v$instance;

STATUS
------------------------
OPEN

2009.9.8

HAクラスタの準備(Oracleインストール編)

今回はOracleDatabase(10g)のインストールの流れだけ紹介します。

まず、
1)DB01サーバにOracleDatabaseをインストールする
※インスタンスの作成はしません。製品のインストールのみします
2)DB02サーバにOracleDatabaseをにインストールする
※インスタンスの作成はしません。製品のインストールのみします
3)DB01サーバにデータベースを作成する(データファイルなどは/oracleディレクトリに作成))
4)DB01サーバのインストールディレクトリ(/opt/app/oracle)をtarアーカイブする
※データベースを作成した状態のソフトウェアをディレクトリごと
5)DB02サーバにtarアーカイブしたファイルをコピーして、展開

これで、DB01サーバとDB02サーバのOracleDatabaseの状態が同じになります。

DB01サーバで共有Diskのマウント・Oracleの起動確認して、Oracleの停止・共有Diskをアンマウント
DB02サーバで共有Diskのマウント・Oracleの起動確認して問題なければOKです。

これで、仮想IPや共有ディスクの切替をスクリプトにしておけば、
手動切替のクラスタ構成の環境までは作成できたことになります。



【手動での切り替え例】

1)運用系で起動します。


[root@db01 CLUSTER_TOOL]# ./cluster_start.sh
mount OK!
VIP OK!
send_arp OK!
Oracle LISTENER START OK!
ORACLEインスタンスが起動しました。

Total System Global Area 100663296 bytes
Fixed Size 1217932 bytes
Variable Size 79694452 bytes
Database Buffers 16777216 bytes
Redo Buffers 2973696 bytes
データベースがマウントされました。
データベースがオープンされました。
Oracle START OK!
[root@db01 CLUSTER_TOOL]#

2)SQLで接続してHOST_NAMEを確認します。


[oracle@db01 ~]$ sqlplus "sys/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orcl))) as sysdba"

SQL*Plus: Release 10.2.0.1.0 - Production on 火 9月 8 22:48:28 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
に接続されました。
SQL> set pagesize 1000
SQL> select HOST_NAME from v$instance;

HOST_NAME
----------------------------------------------------------------
db01.plala.jp

3)運用系で停止します。


[root@db01 CLUSTER_TOOL]# ./cluster_stop.sh
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
Oracle STOP OK!
Oracle LISTENER STOP OK!
VIP STOP OK!
send_arp OK!
Umount OK!
[root@db01 CLUSTER_TOOL]#

4)待機系で起動します。


[root@db02 CLUSTER_TOOL]# ./cluster_start.sh
mount OK!
VIP OK!
send_arp OK!
Oracle LISTENER START OK!
ORACLEインスタンスが起動しました。

Total System Global Area 100663296 bytes
Fixed Size 1217932 bytes
Variable Size 79694452 bytes
Database Buffers 16777216 bytes
Redo Buffers 2973696 bytes
データベースがマウントされました。
データベースがオープンされました。
Oracle START OK!
[root@db02 CLUSTER_TOOL]#

5)もう一度SQLでHOST_NAMEを確認してみます。


SQL>
SQL> exit    ← 一度停止したので、異常になった。
ERROR:
ORA-03113: 通信チャネルでend-of-fileが検出されました

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options (障害を含んでいます。)との接続が切断されました。
[oracle@db01 ~]$ sqlplus "sys/oracle@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.168.1.100)(PORT=1521)))(CONNECT_DATA=(SID=orcl))) as sysdba"

SQL*Plus: Release 10.2.0.1.0 - Production on 火 9月 8 22:52:08 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
に接続されました。
SQL> set pagesize 1000
SQL> select HOST_NAME from v$instance;

HOST_NAME
----------------------------------------------------------------
db02.plala.jp

SQL>

クラスタ切替を行ったので、HOST_NAMEが異なっていることを確認しました。

今回クラスタはスクリプトで実施しましたが、クラスタ製品を用いると
ネットワーク障害(インターコネクトなどが別途必要)や、データベースの
プロセス障害、リスナー障害など検知して、自動切り替えを実装できる
ようになります。

2009.9.7

HAクラスタの準備(仮想IP編)

仮想IPは自ノードのIPアドレスとは別のアドレスを設定して、
ACTIVE/BACKUP構成のサーバ間で引き継ぎをできるようにし
ます。クライアントは仮想IPに向けてアクセスしておけば、
サーバが切替っても、仮想IPは引き継ぐので影響がでません。

※複数台のサーバで1つのIPを使い回すイメージです。

(1) send_arpコマンドを使うので、OSにあったrpm(かソース)を用意してインストール
今回使ったファイル:fake-1.1.8-1.2.el4.rf.i386.rpm
パッケージの検証
rpm -K fake-1.1.8-1.2.el4.rf.i386.rpm
インストールテスト
rpm -ivh --test fake-1.1.8-1.2.el4.rf.i386.rpm
インストール
rpm -ivh fake-1.1.8-1.2.el4.rf.i386.rpm
※アンインストール
rpm -e fake

※警告が出てもインストール&使用はできました。

[root@db01 /]# which send_arp
/usr/sbin/send_arp
これがインストールされたコマンドです。

※send_arpは自身のIPアドレスとMACアドレスを他のノードへ通知します。

(2)仮想IPの設定

vipは10.168.1.100としました。

aliasの追加
ifconfig eth0:0 10.168.1.100

aliasの削除したい場合は「down」をつける
ifconfig eth0:0 10.168.1.100 down

send_arpはこうすれば使用できた
send_arp 10.168.1.100 「MACアドレス」 255.0.0.0 ff:ff:ff:ff:ff:ff

(3)Windowsクライアントからpingで確認

C:\Windows\system32 ping -t -a 10.168.1.100

100.1.168.10.in-addr.arpa [10.168.1.100]に ping を送信しています 32 バイトのデータ:
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64  ←1.ここでDB01のVIPをDOWN
要求がタイムアウトしました。                    ←2.通信できない状態
要求がタイムアウトしました。
要求がタイムアウトしました。                    ←3.DB02にVIPを割当てsend_arpで通知
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64  ←4.DB02に通信できる状態になる
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64
10.168.1.100 からの応答: バイト数 =32 時間 1ms TTL=64

10.168.1.100 の ping 統計:
パケット数: 送信 = 19、受信 = 16、損失 = 3 (15% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 0ms、最大 = 1ms、平均 = 0ms

共有DISKの切換え、仮想IPの切換えが確認できたので、次はOracleインストールしてみます。







2009.9.6

HAクラスタの準備(Disk編)

HAクラスタ環境をvmware上に作成しようと思っているので、
準備としてDiskの設定をしてみました。

※HAクラスタは、複数台のマシンを用意して、運用しているサーバに
障害が発生した場合に、待機しているサーバに機能を移管して、運用
を続けられるようにする構成です。

(1) vmware上にLinuxマシンを2つ作成(ホスト名はDB01,DB02)
(2) 共有Disk(SCSI)を作成
以下の設定が「.vmx」に必要。vmware server2.0はGUIで設定できるみたい

scsi0:1.mode = "independent-persistent"
disk.locking = "false"
diskLib.dataCacheMaxSize = "0"
diskLib.dataCacheMaxReadAheadSize = "0"
diskLib.dataCacheMinReadAheadSize = "0"
diskLib.dataCachePageSize = "4096"
diskLib.maxUnsyncedWrites = "0"
(3) DB01サーバからfdiskでパーティション作成
fdisk /dev/sdb # No.2 SCSI

root@db01 ~]# fdisk /dev/sdb

このディスクのシリンダ数は 1044 に設定されています。
間違いではないのですが、1024 を超えているため、以下の場合
に問題を生じうる事を確認しましょう:
1) ブート時に実行するソフトウェア (例. バージョンが古い LILO)
2) 別の OS のブートやパーティション作成ソフト
(例. DOS FDISK, OS/2 FDISK)

コマンド (m でヘルプ): p

Disk /dev/sdb: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = シリンダ数 of 16065 * 512 = 8225280 bytes

デバイス Boot Start End Blocks Id System
/dev/sdb1 1 1044 8385898+ 83 Linux


(4) XFSでファイルシステムを作成してみる(ファイルシステムは使えれば何でも良いです)

mkfs -t xfs /dev/sdb1
[root@db01 ~]# mkfs -t xfs /dev/sdb1
meta-data=/dev/sdb1 isize=512 agcount=8, agsize=262059 blks
= sectsz=512
data = bsize=4096 blocks=2096472, imaxpct=25
= sunit=0 swidth=0 blks, unwritten=1
naming =version 2 bsize=4096
log =internal log bsize=4096 blocks=2560, version=1
= sectsz=512 sunit=0 blks
realtime =none extsz=65536 blocks=0, rtextents=0

#ラベルの設定
実行前
[root@db01 ~]# xfs_admin -l /dev/sdb1
label = ""
実行
[root@db01 ~]# xfs_admin -L "shared:oracle" /dev/sdb1
writing all SBs
xfs_admin: truncating label length from 13 to 12
new label = "shared:oracl"
実行後
[root@db01 ~]# xfs_admin -l /dev/sdb1
label = "shared:oracl"


(5) mountとumount

#/oracleにマウントしてみる
[root@db01 ~]# mkdir /oracle
[root@db01 ~]# mount -t xfs /dev/sdb1 /oracle
[root@db01 ~]# df -h
Filesystem サイズ 使用 残り 使用% マウント位置
/dev/mapper/VolGroup00-LogVol00 16G 3.6G 11G 25% /
/dev/sda1 99M 13M 82M 14% /boot
none 252M 0 252M 0% /dev/shm
/dev/sdb1 8.0G 160K 8.0G 1% /oracle

#マウント解除してみる
umount /dev/sdb1

[root@db01 ~]# df -h
Filesystem サイズ 使用 残り 使用% マウント位置
/dev/mapper/VolGroup00-LogVol00 16G 3.6G 11G 25% /
/dev/sda1 99M 13M 82M 14% /boot
none 252M 0 252M 0% /dev/shm


(6) DB02サーバでもマウントしてみます

[root@db02 ~]# mkdir /oracle
[root@db02 ~]# mount -t xfs /dev/sdb1 /oracle
mount: スペシャルデバイス /dev/sdb1 が存在しません

[root@db02 ~]# partprobe /dev/sdb
※パーティションは認識したけど「/dev/sdb1」がなかったので、partprobeで作成
[root@db02 ~]# mount -t xfs /dev/sdb1 /oracle
[root@db02 oracle]# df -h
Filesystem サイズ 使用 残り 使用% マウント位置
/dev/mapper/VolGroup00-LogVol00 15G 3.6G 9.9G 27% /
/dev/sda1 99M 13M 82M 14% /boot
none 252M 0 252M 0% /dev/shm
/dev/sdb1 8.0G 160K 8.0G 1% /oracle



共有ディスクの設定とサーバ間のDisk切替(mountレベル)ができることを確認しました。