データベース備忘録

※自分調べ

行移行、行連鎖…

適当に調べて適当にまとめたのでこの記事を見たという、数少ない人は指摘があればコメントしていただけるとありがたいです。

 

行移行、行連鎖…

DB性能劣化の原因である断片化、その要因の主な2つ(ほんとはブロック内連鎖とかもあるらしいが)

 

断片化の種類についてもまとめようと色々調べていたが、以下のリンクに解消方法とともに分かりやすくまとめられていた

blogs.oracle.com

 

 

 

 

本題の行移行と行連鎖

最初調べたとき、1レコードが複数のデータブロックにまたがっちゃうという点では「どっちも同じじゃん」と思っていたが良く調べてみたら違った。

 

 

◆行移行

更新などで1レコードのデータ量が増加、初めに入っていたデータブロック(ブロックA)では収まりきらない、だから別の空きブロック(ブロックB)に移行しよう!で発生する

この際に後から更新したデータのみがブロックBに格納されるわけではなく、既存のデータも一緒にブロックBに移行される。

 

じゃあ既存のデータが入っていたブロックAの領域には何が残るの?って疑問が出てくるが、ブロックAにはブロックBに実データが格納されているよ、というポインタを残す。

行移行は完全な移行ではないので、ROWIDは変更されない

つまり、行移行をしたレコードを検索する際にインデックスを使って検索したとて、初めにブロックAを検索してからブロックBを見に行くので効率が悪い。

 

 

 

◆行連鎖

ドでかいデータを挿入する際に発生する。

一つのデータブロックでは収まりきらないレコードがある場合に、致し方なしということで複数のデータブロックにデータを分割して格納する。

 

行連鎖というか行分割ではないのか?と思ったが、

ブロックAにはブロックBのポインタが、ブロックBにはブロックCのポインタが、ブロックCには…とった感じでブロック同士が一方向に連鎖してデータを格納するから「行連鎖」らしい

 

 

 

行連鎖は結構分かりやすいと思う、「一つの箱では買ってきた物が収まりきらないから複数の箱に分割してしまおう」のイメージ

行移行は初め行連鎖と同じだと思っていたが「物を増やしたら箱に収まらないから、元の箱にメモを残しておいて別の箱に移しちゃおう」のイメージだった。

 

 

 

 

RAC構成でOracle GoldenGateを使う

DB間のリアルタイムデータ同期を実現するGoldenGateをRACで使用する時に、とあるリスクが生じる。

 

GoldenGateではソースDBとターゲットDB間でトレイルと呼ばれる、データ変更情報が書き込まれた証跡ファイルをやり取りするわけだが、ソース側DBがRAC構成(active-active)になっている場合、REDOログ・アーカイブログがインスタンスごとに存在していることで特殊な状況に陥ることがある。

 

インスタンスが一つの場合、SCN(System Change Number)順に行儀良くREDOログに入っていき、GoldenGateは順番通りに読み込んでくれる。

それがRAC構成だと、インスタンスごとに投入されるので、GoldenGateが読み込む順番がちぐはぐになる可能性がある

 

つまり、

GoldenGate(というかCaptureプロセス)がトレイルに書き出すため

インスタンスAのREDOでSCN002を読み込んだ後に、

インスタンスBのREDOでSCN001を読み込んでしまう

のようなこと(後からより古い更新履歴を読み込んでしまう)が起こりうる

 

エラーメッセージとしては以下のような感じ

(読み込んだSCNが既に読み込んだSCNより古いぞ、と言っている)

OGG-00694、OGG-00695

encountered commit SCN<n.xxx> that is not greater than the highest SCN already processed

 

ちなみにこれ完全に防ぐ手立てはないらしく、REDOログからトレイルに書き出す時間に余裕(待機時間)を持たせることで、起こりにくくすることはできる。

 

threadoptions MAXCOMMITPROPAGATIONDELAY xxxxx IOLATENCY xxxxx

 

MAXCOMMITPROPAGATIONDELAY ・・・

oracleREDOに書き込みを行った時間とGG(Capture)がREDO を読み込む時間のラグを許容する時間を設定できる

IOLATENCY ・・・

I/Oに関する許容する遅延時間を設定できる

 

上記二つを合わせた時間分、CaptureがREDOを読み込みに行くのを待機する。

そうすることで、なるべくCaptureプロセスは順序通りにREDOを読み込み・トレイルに出力することが可能になるので事象が起こりにくくすることが可能になる。

ただ、あくまで起こりにくくするだけでRAC構成、かつ両系が稼働系の場合は発生しうる事象になるため、本当に回避したい場合はDBの稼働系・待機系を明示的にして運用するしかなさそうだ。

 

完全リカバリと不完全リカバリ

【完全リカバリ

その名の通り障害発生時点までを完全に戻す。

過去取得したバックアップからバックアップ地点までリストア、そこからバックアップ以降のアーカイブログを適用して障害発生時点までリストアさせる

 

【不完全リカバリ

「過去の特定の時間」までリカバリする。

過去取得したバックアップからバックアップ地点までリストア、までは同じだが、アーカイブログを途中まで適用させることで特定の時間までリカバリさせる。

 

リカバリ後、データベースをオープンする際にresetlogsでREDOログのリセットをしなければならない。使用しなかったアーカイブログは使用しないことになるので、不完全リカバリ後から新たにREDO&アーカイブログを出力しなければならないから。

 

 

 

restoreとrecovery

restore と recovery

 

未だにごっちゃになるが

restore は「蓄えから復元すること」

recovery は「埋め合わせること」なので

 

Oracle的には

過去取得したバックアップ(蓄え)から戻すことをリストア、

アーカイブ(またはredo)ログを適用して障害発生日時まで埋め合わせることをリカバリ

になる

 

英語話者は言葉の意味的に理解出来るだろうが、日本人は「リストアとリカバリ」って言われても同じ意味に聞こえてしまうので難しい…

virtualbox(Windows上) にcentos7をインストール、からのOracle12cr2をインストールしてDB作成した日(メモ)

参考にしたサイト

 

virtualbox(Windows上) にcentos7をインストール

https://qiita.com/100/items/80a899fbaeb1e82b3f67

 

そういえばOracleインストール資材をDLしてもゲストOSに持っていけないと気付き、

②共有フォルダ設定

https://qiita.com/SUZUKI_Masaya/items/fb2d3c8141ba82d16801

 

③Oracle12cr2をインストール~DB作成

https://qiita.com/danishi/items/1e8b25c62e9240e098aa

リスナーはNet Configuration Assistant(NETCA)で作成しなくても、DBCAでDB作成時に合わせて作成できる

 

★困ったこと

③のDB作成時、自動共有メモリー管理設定でSGA・PGAサイズを決める際に

[DBT-11209]現在使用可能な物理メモリーは、データベースの作成に必要な物理メモリー(3236MB)を下回っています。

DBT-11205: 指定された共有プール・サイズが、推奨最小サイズ要件を満たしていません。これにより、データベース作成が失敗する可能性があります。

のエラー

 

SGA・PGAのサイズをいくら落としても作成出来ない…と思っていたら、そもそもホストOSのメモリ量が少なかった。

下記を参考にメモリ増量

https://pc-karuma.net/virtualbox-change-memory-size/

 

 

 

Oracleでこれコミットしなくて良いの?って思った日

とあるテーブルにレコードをINSERT

INSERT後、確認のためにSELECT

 

INSERTのSQLファイルには「insert~」の一文しか入っていないにも関わらず、SELECTのSQLファイルを実行したらちゃんと更新されている。。。

 

SELECTのSQLファイルにもcommitは書いてない。。。

 

なんでだ…と思ってコミットタイミングを調べてみる

次のような状況では、Oracle Databaseによって暗黙的なCOMMITが発行されます。

  • 構文が有効なデータ定義言語(DDL)文の前(文がエラーになる場合も同様)

  • エラーが発生することなく完了するデータ定義言語(DDL)文の後

 

DDL…?

SELECTのSQLファイルをよく見てみると

 

ALTER SESSION SET NLS_DATE_FORMAT = 'RR/MM/DD HH24:MI:SS';

 

みたいなDDLを打っていた

(対象のテーブルに日付カラムがあったから)

 

なるほど納得

commitを明示的に打たなくてもこういうDDLを打っておくことで暗黙的にcommitできるのは便利かも