オフライン中のトランザクションについての疑問

このQ&Aのポイント
  • オフライン中のトランザクションはなぜ整合がとれるのか
  • コミットやロールバック情報の保持場所について疑問
  • トランザクションをオフラインにした後の操作について不思議
回答を見る
  • ベストアンサー

オフライン中のトランザクションについて

表領域をオフラインにした場合、オフライン前に開始されたトランザクションは有効ですが、オフラインのまま、コミット、または、ロールバックして、表領域をオンラインにしても、整合がとれるのはなぜなのでしょうか。 コミットするか、ロールバックするかの情報はどこに保持してるのか疑問です。 (オフラインにしてから、ファイルをリネームし、 トランザクションをロールバックして、 ログをアーカイブし、DB再起動後に、ファイル名を戻して、 オンラインにすると、ちゃんとロールバックされています。 同じ操作で、コミットするとちゃんとコミットされています。 知っている方には当然なのでしょうが、私にとっては、不思議です) 詳しい方がみえましたらご教授お願いいたします。

  • Oracle
  • 回答数6
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.6

データベース概要のマニュアルに 「表領域がオフラインになると、Oracleでは後続のSQL文でその表領域内に含まれるオブジェクトを参照できなくなります。表領域内のデータを参照する完了済の文を含むアクティブ・トランザクションは、トランザクション・レベルでは影響を受けません。それらの完了済の文に対応するロールバック・データは、SYSTEM表領域にある遅延ロールバック・セグメントに保存されます。表領域が再びオンライン化されると、このロールバック・データは必要に応じて表領域に適用されます。」 とあるので「SYSTEM表領域にある遅延ロールバック・セグメントに保存」されるようです。

taro12306
質問者

お礼

ありがとうございます!! まさに、知りたかった内容が、"遅延ロールバック・セグメント" を検索することで知ることができました。 本当にありがとうございました!

その他の回答 (5)

回答No.5

>ひょっとして、オフラインの表領域のトランザクションが未確定の場合、 >ログスイッチによって、その部分のログがアーカイブされないで >カレントログに残るってことでしょうか? 「オフラインの表領域のトランザクションが未確定の場合、」というのはcommit/rollbackしていないトランザクションを指しますか? commit/rollbackしていないトランザクションはREDOログバッファにあって、REDOLOGファイルには基本的には入りません。 (例外:REDO ログ・バッファがいっぱいになるか、別のトランザクションがコミットされるなどでREDOログファイルに含まれます) 表領域をオフラインにする際(NORMAL(デフォルト)指定)、データベースは表領域のデータ・ファイルすべてのチェックポイントを取ってから、それらのファイルをオフライン化します。

taro12306
質問者

補足

>ひょっとして、オフラインの表領域のトランザクションが未確定の場合、 すいません。 オフラインの表領域のトランザクションがコミット・ロールバックされた場合 の間違いでした。 >表領域をオフラインにする際(NORMAL(デフォルト)指定)、データベースは表領域のデータ・ファイルすべてのチェックポイントを取ってから、それらのファイルをオフライン化します。 そのとおりなのですが、、 わからないのは、オフライン化の後で、コミット・ロールバックした場合、 その情報をどこに保持してるかが知りたいのですが、、、。

回答No.4

あまり自身ないですが・・・。 変更の情報はREDOログにあります。 インスタンスリカバリに関してはcommitした/しないに関わらず、適用し、その後にcommitしていない情報をrollbackします。 REDOログに残っているのであれば、インスタンスリカバリでREDOが適用されてcommitされた内容が表示されているのだと思います。 #REDOログが上書きされるタイミングで対象表領域すべてがOFFLINEだとどうなるかは不明ですけど・・・ また、トランザクションがコミットされると、ロールバックまたはトランザクション・リカバリの実行にUNDO データは不要になります。とマニュアル(10g)にあるのでcommit後のUNDOの変更は関係ないと思います。

taro12306
質問者

補足

回答ありがとうございます。 >変更の情報はREDOログにあります。 >インスタンスリカバリに関してはcommitした/しないに関わらず、適用し、その後にcommitしていない情報をrollbackします。 >REDOログに残っているのであれば、インスタンスリカバリでREDOが適用されてcommitされた内容が表示されているのだと思います。 ひょっとして、オフラインの表領域のトランザクションが未確定の場合、 ログスイッチによって、その部分のログがアーカイブされないで カレントログに残るってことでしょうか? ただ、検証が難しそうですね、、。

  • MZ-80B
  • ベストアンサー率56% (46/81)
回答No.3

> 不完全リカバリになるのではないかな・・・ 「ログをアーカイブし、~」と書かれていますから アーカイブログ運用しているということですよね。 不完全リカバリになる。ではなくアーカイブを使って 完全リカバリ可能に訂正いたします。

  • MZ-80B
  • ベストアンサー率56% (46/81)
回答No.2

UNDO表領域を変更とは 正常なUNDO表領域の切り替えですか?メディアリカバリですか? デフォルトの切り替えであればUNDOセグメントヘッダ情報が 移動したのではないでしょうか

taro12306
質問者

補足

以下のようにUNDO表領域をUNDOTBS01 -> UNDOTBS02に変更しました。 shutdown immediate; startup nomount; alter system set undo_tablespace = 'UNDOTBS02' scope=spfile; alter database mount; alter database open; オープン時には、UNDOTBS01にはoracleからアクセスできないと思うので、 UNDOセグメントヘッダ情報が移動はできないような気がするのですが、、

  • MZ-80B
  • ベストアンサー率56% (46/81)
回答No.1

質問内容はデータ表領域がオフラインなのになぜコミットできるかというと同じです。 コミット操作はUNDOセグメント(ロールバックセグメント)ヘッダの トランザクション表にSCN付きで記録されますのでデータ表領域のIOは遅延することができます。 次の表アクセス時にUNDOセグメントヘッダからデータ表領域に書き込まれます。 シャットダウンしてUNDO表領域も同時に壊しておくと、たぶんオフライン前までの 不完全リカバリになるのではないかな・・・

taro12306
質問者

補足

回答ありがとうございます。 早速、以下のように検証してみました。 更新処理 -> オフラインに変更 -> コミット -> シャットダウン -> UNDO表領域を変更 -> オープン -> オンラインに変更 残念ながら、正しくコミットしたデータが確認できてしまいました。 ロールバックでも正しくロールバックしたデータが確認できました。 ひょっとして、SYSTEM表領域にこっそり情報を保持してるんでしょうか?

関連するQ&A

  • トランザクション処理について

    トランザクション処理について、ちょっと疑問に思うことがあります。 トランザクション処理とは、クライアントの異常終了などで、中途半端な状態で終わったデータはロールバックされ、元の状態にもどされることですよね?では、サーバが突然フリーズした場合どうなるのでしょうか?トランザクション処理もできないため、中途半端な状態で終わったデータは手動で整合性を合わせる必要があるのでしょうか? かなり、基本的なことを聞いていますが、DBの知識がないためどなたか教えてください。

  • PHP-オラクルでのトランザクション

    PHP-オラクルでのトランザクションについて 教えてください。 *すべてPHP(OCI8関数)のWEBアプリからが前提です。 1.OCIExecute()でOCI_DEFAULT(自動コミットOFF)を指定した状態で   コミット(OCICommit)をせずにログオフ(OCILogoff)した場合、 コミットされるのか、それともロールバックされるのか? 2.OCIExecute()でOCI_DEFAULT(自動コミットOFF)を指定した状態で   コミット(OCICommit)もログオフ(OCILogoff)もしていない状態で WEBブラウザを閉じた場合、コミットされるのか、それとも   ロールバックされるのか? の2点です。自分で試せればいいのですが、もうしばらくの間 オラクル環境がないまま、プログラムを作成しなければならない状況です。。。 ご存知の方がおりましたらご教授していただければ幸いです。 よろしくお願いします。

  • ACCESSでのトランザクション処理

    VB6+ACCESS2000で開発をしております。 VBとACCESSとの接続はADOでおこなっております。 ACCESSはそれほど使ったことがないのでよくわからないのですが、ACCESSでトランザクション処理はできるのでしょうか? ロールバックもコミットも見たところありませんでした。 教えてください。

  • トランザクションを張って対話型でのコミット・ロール

    トランザクションを張って更新処理を行った後に、 ユーザの「はい」「いいえ」ボタンによって、 トランザクションのコミットとロールバックを切り替えることは可能でしょうか。 処理の流れは以下の様になります。 1.データ更新前の値を取得 2.トランザクションの開始 3.データ更新 4.データ更新前の値とデータ更新後の値を比較して、   差分がある場合は確認メッセージを表示する。 5.確認メッセージで「はい」がクリックされた場合はコミットする。 6.確認メッセージで「いいえ」がクリックされた場合はロールバックする。 実装方法はどのようでも構いません。 どなたかご教授ください。

  • mysqlでCSVインポートでトランザクション管理出来る

    只今、mysqlを使用して開発しております。 行き詰まっておりまして 大変申し訳ありませんが、ご教授の程、よろしくお願いいたします。 要件は以下になります。 ・CSVファイルデータをインポートする。 ・CSVファイルは複数なので、全ての処理が終わった段階でコミット・もしくはロールバックする。 (トランザクション管理が出来ればよいです。) ※LOAD DATA INFILEでトランザクション管理しようとしたのですが LAODのトランザクション管理は5.1系じゃないと出来ないようですので、 出来ませんでした。 mysqlのバージョン :5.0.24

    • ベストアンサー
    • MySQL
  • トランザクションログファイルが肥大化

    トランザクションファイルが20Gに肥大化して、サーバのディスク容量を圧迫しています。 適正なログ容量で管理したいのですが方法がいまいちわかりません。ログ切捨てとか、ログ領域をデフォルテの自動拡張から容量指定にしたいと思っています。DBのメンテンスに関するサイトがあったら教えてください。

  • トランザクションとlast_insert_id

    トランザクション中にinsertする予定のテーブル(未コミット)のauto_increment値を取得することはできるのでしょうか。 以下のような処理を期待しているのですが、hoge1テーブルのauto_increment値が取得できずに困っております。last_insert_id に関わらず、hoge1テーブルのauto_increment値が取得できる方法があれば教えてください。 (1) トランザクション開始 (2) $sql=" INSERT INTO hoge1(name) value('あああ'); "; (3) ( ロールバック ) (4) $key=mysql_insert_id(); (5) $sql2=" INSERT INTO hoge2(hoge1_primary,age) value($key,'20歳'); "; (6) ( ロールバック ) (7) コミット (8) トランザクション終了 よろしくお願いします。 環境: php5,mysql5 (InnoDB)

    • ベストアンサー
    • MySQL
  • トランザクション管理について

    皆さんはトランザクション管理を何処で行ってますか? 大体のプロジェクトでは以下の2パターンに集約されると思います。 1.ビジネスロジックでトランザクション管理して、DAOへ引数としてトランザクションを渡す。  当然、コミット・ロールバックはビジネスロジック側で管理。 2.ビジネスロジック側では管理せず、DAO側で管理。  ビジネスロジックへは結果のみ返却。 実は今回のプロジェクト、Java初心者(プログラムって何?レベルとC++なら受講したことあるよ!レベル)が9割を占めるチームです。 初心者の方々はビジネスロジックを設計・実装します。 それ以外の部分(DB・SpringFramework等)を私が設計・実装します。 ビジネスロジックの部分の設計も、概要設計レベルしか記述されておらず、トランザクション無視の設計しかありません。 バグにまみれてデスマーチなんてごめんなので、2のパターンでトランザクションからDB周りを設計したいと思っているのですが、リーダー(スキルは不明。経験はあるらしい)が「DAO側でやると上手くいかない場合が多い」と言われ、却下されそうです。 何処がどう上手くいかないのか聞いても、明確に返答は貰えません。 でもなんとか2のパターンでいきたいのですが、上手い説得方法が見つかりません。 なんて言えば納得してくれそうか、皆様のお知恵を拝借したく投稿しました。 足らない部分は補足させていただきます。 よろしくお願いします。

    • ベストアンサー
    • Java
  • C# トランザクション処理

    DataSetのTableAdapterでSQL Serverへのデータ挿入、更新、削除を行います。 try { ta.UpdataQuery(.....); } catche { Exception; } といった処理をしますが、トランザクション処理をする場合、 try { // トランザクション開始 ta.UpdataQuery(.....); // コミット } catche { // ロールバック Exception; } といった感じになるかと思いますが、どのようにコードを書けばよいのでしょうか?手元にコードがありませんので詳細が書けませんが、よろしくお願いします。

  • なぜtry{}catch(){}の中?

    DBへの更新を行う際に 私は try{ トランザクションスタート 処理 コミット }catch(Exception e){ ロールバック } の書き方をしていますが トランザクションスタート try{ 処理 コミット }catch(Exception e){ ロールバック } の書き方をしている人がいたので try{}catch(){}の中に トランザクションスタートを入れて下さいと伝えたところ なぜ?try{}catch(){}の中に入れるのか聞かれたのですが 答えられませんでした。 ネットにて色々なソースコードをみても try{}catch(){}の中に書かれているのでそういうモノとして 覚えているのですが、なぜ中なのでしょうか?

    • ベストアンサー
    • PHP