揮発性のメモ2

http://d.hatena.ne.jp/iww/

ORA-12560

RAC構成で片系が死んでいるとき、ときどきエラーになる

ORA-12560: TNS: プロトコル・アダプタ・エラーが発生しました

このエラーが発生しているときは、内部でconnect()がエラーになっている。そのときの接続先が死んでいる系になっていたところまでは前に確認した。
いろいろ行き当たりばったりで調査したところ、tnsnames.ora負荷分散を有効にしていると死んでいる系へのアクセスになることがある。ような気がする。

HOGE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracle01-vip)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracle02-vip)(PORT = 1521))
    (LOAD_BALANCE = no) ★これ
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = TEST)
    )
  )

LOAD_BALANCEnoにして様子見。これで直ったらラッキーだと思う。


これを設定しても、片系が死んだ直後は接続が不安定になる。5分くらいすれば安定する。Oracleは障害に弱いのでこのくらいは我慢するしかない。

あとでリトライした方がいいエラー

リトライしてもだいたい無意味。クエリとかデータ的におかしいから

  • ORA-00001: 一意制約(HOGE.SYS_C0000001)に反しています
  • ORA-00979: GROUP BYの式ではありません。
  • ORA-01400: ("HOGE"."PIYO"."FUGA")にはNULLは挿入できません。
  • ORA-01445: キー保存表なしに結合ビューからROWID を選択できません。
  • ORA-01839: 指定された月に対して日付が無効です
  • ORA-01843: 指定した月が無効です。
  • ORA-01847: 月単位の日付は1から月末日の間で指定する必要があります


あとでリトライを試してみる。インフラとかの調子が悪かったりするだけだから。データ収集関係のものなら特に

  • ORA-00257: アーカイブ・エラーです。解除されるまで内部接続のみにしてください。
  • ORA-01034: ORACLE not available
  • ORA-12528: TNS:リスナー: 該当するインスタンスはすべて、新規接続をブロックしています
  • ORA-12541: TNS: リスナーがありません
  • ORA-12560: TNS: プロトコル・アダプタ・エラーが発生しました

ノーアーカイブログモードに切り替えたい

10gR1
ノーアーカイブログ モード運用への移行 - オラクル・Oracleをマスターするための基本と仕組み
ここを参考に、ノーアーカイブログモードに切り替えるテスト

SQL> SHUTDOWN IMMEDIATE
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SQL> STARTUP NOMOUNT
ORA-12528: TNS:リスナー: 該当するインスタンスはすべて、新規接続をブロックしています

ここでエラー。
RAC構成のときはこの手順はNG。のような気がする。

RAC構成のOracleで片系だけ管理者権限で接続できなくなったとき

http://www.oracle.co.jp/forum/thread.jspa?threadID=2001432
とおんなじような現象がおきたのでメモ

現象

管理者でTEST2には普通に接続できるが、TESTではアイドルインスタンスになってしまう。
(もう片方のノードではとくに問題ない)

$ sqlplus sys/password@TEST2 as sysdba
に接続されました。
SQL> SELECT status FROM v$instance;

STATUS
------------
OPEN
$ sqlplus sys/password@TEST as sysdba
アイドル・インスタンスに接続しました。

SQL> SELECT status FROM v$instance;
SELECT status FROM v$instance
*
行1でエラーが発生しました。:
ORA-01034: ORACLE not available

対処

TEST2で接続してデータベースをいったん止めて、TESTとして一気に動かす

$ sqlplus sys/password@TEST2 as sysdba
SQL> SHUTDOWN IMMEDIATE
SQL> quit
$ srvctl start database -d TEST

とりあえず問題は解決したので終わり

Cluster Ready Service が起動しないとき

Apr 19 09:25:20 oracle01 logger: (Oracle CRSD is running. CRSD must be terminated before another CRSD can be started) 
Apr 19 09:25:20 oracle01 su(pam_unix)[3404]: session opened for user oracle by (uid=0)
Apr 19 09:25:20 oracle01 su(pam_unix)[3404]: session closed for user oracle
Apr 19 09:25:20 oracle01 logger: (Oracle CRSD is running. CRSD must be terminated before another CRSD can be started) 
Apr 19 09:25:20 oracle01 init: Id "h3" respawning too fast: disabled for 5 minutes

init.crsdは起動時にときどき死ぬが、そのときにPIDファイルが残っていて再起動が必ずコケる。Oracleの二重のバグ。


init.crsdの起動オプションは3つ

  • start 起動するフラグを立てる(/etc/init.d/init.crsから)
  • stop 停止する(/etc/init.d/init.crsから)
  • run 起動する(/etc/inittab から)

startを実施すると、再起動フラグが立つ。


CRSの本体はinittabで起動する

h1:35:respawn:/etc/init.d/init.evmd run >/dev/null 2>&1 </dev/null
h2:35:respawn:/etc/init.d/init.cssd fatal >/dev/null 2>&1 </dev/null
h3:35:respawn:/etc/init.d/init.crsd run >/dev/null 2>&1 </dev/null

init.crsd runは、起動時にPIDファイルを確認し、存在すれば(すでに起動していると判断し)エラーを吐いて終了する。
このとき、再起動フラグが立っていたら起動済みのinit.crsdを殺し、PIDファイルも消し、次のinit.crsd runで正常に起動するように準備する。

/etc/init.d/init.crsd stop
/etc/init.d/init.crsd start

最長で5分くらい待てば正常に起動する。はず。

PDOを使って OracleでLIMITを実装する

前やった方法⇒OracleでLIMITを実装する - 揮発性のメモ
これだと、副問い合わせ(インラインビュー)されるので、外部結合してカラム数が1000超えてるときとかにエラーになってしまう。


PDOを使う方法

SELECT a,b,c FROM hoge ORDER BY a LIMIT 10,20;
$query = "SELECT a,b,c FROM hoge ORDER BY a";
$offset = 10;
$count  = 20;


$sth = $dbh->prepare( $query, array( PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL ) );
//for( $i=0; $i<$count; $i++ ){
for( $i=1; $i<=$count; $i++ ){
    $datas = $sth->fetch( PDO::FETCH_ASSOC, PDO::FETCH_ORI_ABS, $offset+$i );
    if( $datas===FALSE )break;
    // なんか処理
}
$sth->closeCursor();

プリフェッチするときにカーソルがスクロール可能であると設定して、フェッチするときにカーソルの絶対位置を指定する。
必要な個数だけフェッチしたらあとは破棄する。
※カーソルの位置はどうも1始まりっぽい。

長所:副問い合わせがなくなってすっきりする
短所:なんか遅い

表の結合

ORA-01445: キー保存表なしに結合ビューからROWID を選択できません。

表を外部結合して列数が1050を超えるとエラーになる話。


ORA-01445が出るパターン

SELECT hoge.*, piyo.* FROM hoge LEFT JOIN piyo ON hoge.id = piyo.id;

Oracle語に変換すれば出なくなる

SELECT hoge.*, piyo.* FROM hoge,piyo WHERE hoge.id = piyo.id (+);

(+)はあってもなくてもいい方につける。具体的にはLEFT JOINのときは後ろの方につける。INNER JOINのときはつけない。