スキップしてメイン コンテンツに移動

投稿

COMMITについて少し考えてみた(1)

この記事は、 JPOUG Advent Calendar 2019  の22日目の記事です。 21日目はryota_hnkさんの 11gしか知らないオッサンが19cを触る でした。そして、なんと5年ぶりにJPOUG Advent Calendarで書くのですが(そもそも、このブログで何か書くのも5年ぶり...)、最近ちょっと考えてみた誰もが知っていて日常的に使っている「COMMIT」について書いてみたいと思います。 COMMITにおけるREDOログへの同期I/Oがパフォーマンス上問題になっている際によく観測される待機イベントは皆さんがご存知の"log file sync"になるのですが、ここでは深く触れません。"log file sync"について知りたい方は、以下、かなり昔にCOMMITにまつわるLog Writerの仕組みを書いたので参考にしてもらえると良いと思います。(ブラウザで見ると文字化けする部分があるのですが、ダウンロードするときれいに見えるとフィードバックをもらっています) Dbts2013 特濃jpoug log_file_sync from Koji Shinkubo COMMITの仕組みのおさらい 今回は、普段あまり気にしない(と思われる)COMMITの「失敗」や「成功」、さらにCOMMITの結果が「不明」といった状況について考えてみたいと思います。知っている人も多いと思いますが、念の為COMMITを実行した時の動き(若干デフォルメされ複数存在するlog writer workerはlg00と記載してます)を確認しておきます。 18c(12c以降)でのコミット時のシーケンス図 sqlplusなどクライアントは"COMMIT"という文字列をwrite(2)でServer Processのソケットに書き込みます "COMMIT"を受け取ったServer Processはsemctl(2)でlog writer(lgwr)を起床させます 起床したlog writer worker(lg00)はpwrite64(2)でオンラインREDOログにlog bufferの内容およびCOMMIT自体のchange vecto
最近の投稿

ORA-29707: inconsistent value 254 for initialization parameter 4955 with other instances

Oracle 18c(18.3)のDBCAでRACを構築する際にエラーが発生していたので備忘録です。 Oracle 18cのDBCAでRACを構築中に以下のようなエラーに遭遇された方はいませんか?世の中に情報がなかったので、もしかしたら私の環境だけ発生しているのかも知れません。 DBCAの"Completing Database Creation"フェーズで発生していて、RACの2ノード目が起動しないというエラーですが原因はタイトルの通り"ORA-29707: inconsistent value 254 for initialization parameter 4955 with other instances"で、日本語にすると"他のインスタンスの初期化パラメータ 4955 の一貫性のない値 254 によりORA-29707が発生している"ということのようです。 初期化パラメータ 4955 では意味不明ですが、きっとパラメータの番号は4955だろうと忖度しつつ、起動している1ノード目のv$parameterの値を確認してみます。 SQL> select name,value from v$parameter where num=4955; NAME VALUE ---------- -------------------- max_pdbs 5 なるほど、理由はともかくパラメータ番号4955のmax_pdbsの値がノード間で異なっているのが問題なのだろうと想像できます。 そこで、DBCAでRACを構築する際に以下のような感じでmax_pdbsの値を明示的に指定してみます。 左下のAll Initialization Parameters...ボタンをクリックします。 右上のShow advanced parametersにチェックを入れて、max_pdbsパラメータに値を指定し、spfileにも含めるようチェックを入れます。 今回は、エラー発生時に1ノード目で確認したmax_pdbsの値 (5)を設定しました。 このまま、RAC構築を進めると先ほどはエラーとなっていた箇所を見事通過し無事にRAC構築ができました。

COMMITについて少し考えてみた(4)

前回 、Oracleの場合と同様にPostgreSQLのCOMMIT失敗時にトランザクションの結果が不定になる状況を確認しました。 今回は、PostgreSQL 10から導入された行方不明になってしまったトランザクションの結果を確認するtxid_status()について確認してみます。 前回のCOMMIT問題のまとめ txid_status()を使う流れ txid_status()でトランザクションの結果が不明になった状態を確認する大まかな流れは以下のような感じになります。 COMMIT前のトランザクションIDをtxid_current()もしくはtxid_current_if_assigned()で取得しておく COMMITの状態が不明になった場合に、1で取得したtxidを引数にしてtxid_status()でトランザクションの状態を確認する 前回 と同じ方法でCOMMITエラーを発生させてみる WALファイルへの書き込み完了前に障害が発生した場合 1) INSERTを実行(AUTOCOMMITはoffに設定) postgres=# insert into sample_table values (1); 2) txid_current()でトランザクションIDを取得 postgres=# select txid_current(); txid_current -------------- 627 (1 行) 3) backendのrecvfrom(2)をブロック(上記シーケンス図の①の部分) postgres=# select pg_backend_pid(); pg_backend_pid ---------------- 18623 (1 行) $ gdb -p 18623 ... (gdb) catch syscall recvfrom Catchpoint 1 (syscall 'recvfrom' [45]) (gdb) c Continuing. 4) COMMITを実行 postgres=# commit; 上記の状態でCOMMITが完了することはありません 5) この状

COMMITについて少し考えてみた(3)

前回 、Oracleのトランザクションガードについて見てみました。 せっかくなので、というか単純に興味があったのでPostgreSQLのCOMMITの動きやOracleと同じく障害発生のタイミングによりトランザクションが行方不明になった時の対処方法を見てみたいと思います。 PostgreSQLのCOMMITの様子 とてもざっくりですが、PostgreSQLのCOMMITの様子を見てみます。 PostgreSQL 11のcommitの動き psqlなどクライアントは"COMMIT"という文字列をsendto(2)でbackendのソケットに書き込みます クライアントからのI/Oイベントにより起床したbackendは以下の処理を行います recvfrom(2)で"COMMIT"を受け取る write(2)でWALファイルにlog bufferの内容を書き出す write(2)でWALに書き出した後backendは以下の処理を行います fdatasync(2)でファイルシステムのキャッシュにあるデータを物理デバイスと同期させる sendto(2)によりクライアントにCOMMIT完了のメッセージを送信 recvfrom(2)でメッセージを受け取ったクライアントは最終的にCOMMIT完了の処理を実施(psqlの場合はコンソールに"COMMIT"を書き出す) 余談 ちなみに、PostgreSQLにwalwriterというプロセスがいますが"COMMIT"に限定すると通常のwalwriterはその名前から想像できるようなWALファイルへの書き込みを実行しません。walwriterは5秒おき(*)にlog bufferの内容をコミットの有無に関係なくWALファイルに書き込みを実施しますがCOMMIT時の同期書き込みはbackendが実施しています。しかし、トランザクションが非同期コミットとして設定される場合(synchronous_commit=offの場合)では、backendに送られたCOMMITをトリガーにCOMMIT自体のWAL recordがwalwriterにより非同期、バッチ的にWALファイルに書き込まれます。 5秒(wal_w

COMMITについて少し考えてみた(2)

前回 、COMMITの失敗時にトランザクションの成否は未確定で、タイミングによっては成功している場合もあるし、失敗している場合もあることを検証しました。 今回は、そのような不安定なトランザクションの状態を確認する方法としてOracle 12c R1からサポートされたトランザクションガードがどのようなものが確認してみます。 前回のCOMMIT問題のまとめ トランザクションガードの前提 トランザクションガードはOracle 12c R1以降でサポートされます。また、次に示す クライアント・ドライバをサポートしています。 12c JDBCタイプ4(Thin)ドライバ 12c OCI、OCCIクライアント・ドライバ 12c Oracle Data Provider for .NET (ODP.NET)、管理対象外ドライバ 12c ODP.NET、ODAC 12c リリース4以降の管理対象ドライバ 詳細は データベース開発ガイド を確認してください。 トランザクションガードを使うための準備 今回は、JDBC(Thin)ドライバを使ってトランザクションガードの動きを確認してみますがいくつか準備を実施します。 トランザクションガードに対応するサービスの作成(変更) 以下のようなSQLでサービスを作成しますが、COMMIT_OUTCOME=TRUEおよびRETENTION_TIMEOUTを適切なサイズにしてサービスを作成(変更)する必要があります。(以下はサービスを作成しています) DECLARE PARAMETER_ARRAY DBMS_SERVICE.SVC_PARAMETER_ARRAY; BEGIN PARAMETER_ARRAY('COMMIT_OUTCOME'):='true'; PARAMETER_ARRAY('RETENTION_TIMEOUT'):=604800; DBMS_SERVICE.CREATE_SERVICE( 'TX_GUARD','TX_GUARD',PARAMETER_ARRAY); DBMS_SERVICE.START_SERVICE('

疑似コードで、昨今のIn-Memoryとかカラム型とかを味わう

とうとう、 JPOUG Advent Calendar 2014 も最終日となりました。今年もご参加頂いた皆様に感謝しつつも、去年に続き、オオトリを務めさせていただきます。 Oracleデータベースも12.1.0.2というバージョンでIn-Memoryかつカラム型で分析系ワークロード用を高速化するオプションが導入されていることはご存じの通りです。 このIn-Memoryオプションという文脈で "ディスクは遅くメモリーは速い。だからIn-Memoryなデータベースは速い" とか "分析系ワークロードはカラム型といったデータフォーマット合っている。だからカラム型が速い" とか "データベースの処理をSIMD(シムディー)とかVector処理といった処理で行うと速い" とか なかなか、上記のキーワードがどのようにデータベース処理と関連しているか不明な状態で説明されることが多いのではないか。と思う今日この頃です。 今日は、In-Memoryやカラム型やSIMDといったキーワードを自分なりに関連あることとして、ここにメモ書きを残そうと思います。 言葉でアレコレ説明しても、よく分からん。(どなたかはSIMDの気持が知りたい。と仰っていた)なので、とてつもなくシンプルな疑似コードで説明してみたいと思います。 * ちなみに、以下示される疑似コードはOracleとも他のデータベースの作りとも全く関係ありません。目的は、疑似コードで処理のイメージを掴めれば良い程度の簡単なものです。(要はこんなにデータ構造はシンプルではないですし、コードもこんなに非汎用的ではないですし、正直、WHERE句のSIMD適用はこんなにお手軽ではないですし) 前提) 以下のような数十カラムを含むテーブル構成で1億件のランダムなデータが入っていると想定 SQLで書くと以下のような感じ create table large_table ( l_quantity number ,l_tax number ,... ,(沢山) ,... ); こんなテーブルをコードで書くと(とりあえずC)、以下のような構造体の配列(これは通常のロー型を想定)になると思います typedef stru

12cでリソースの共有と非共有のはざまで... その3

I/Oリソース編  これまで、マルチテナント・アーキテクチャにおけるCPUリソース、Memoryリソースの制御方法を考察してきたが最後にI/Oリソースの制御について考えてみる。  Oracle Databaseは共有ディスクアーキテクチャーをとることから、従来からI/Oはボトルネックになりやすい重要なコンポーネントだった。マルチテナント・アーキテクチャにより、多くのインスタンスが集約されるとさらに、I/Oのリソース管理の重要性が増してくることは明らかである。  さらに、初回のCPUリソース編でも述べたが、Database Resource ManagerではI/Oのリソース管理は提供されておらず(*1)I/Oリソース管理をするにはExadataによりI/O Resource Managerを使用する必要がある。  筆者はExadataを検証環境として持ち合わせていないので、ここでExadata I/O Resource Managerの検証結果を記載できない。  そこで、CPUリソース編で説明したOSネイティブなリソースマネージャ(*2)を使用したI/Oリソースの管理の方法を紹介したい。 (*1) Runaway SessionとしてのI/Oリソース管理は提供されている (*2) Linuxのcgroupsと初期化パラメーターPROCESSOR_GROUP_NAMEを使用する I/Oリソース制御としてPROCESSOR_GROUP_NAME  初回のCPUリソース編で初期化パラメーターPROCESSOR_GROUP_NAMEを紹介したが、これはPROCESSORに限らずOSの持つcgroups(本件検証環境はOracle Linux 6.4 x86_64)の全ての機能を使用できる。 注意 cgroupsの機能をOracle Database 12 c がどこまでサポートしているか明確なドキュメントはなく、現時点は検証目的としてPROCESSOR_GROUP_NAMEでcgroupsのI/O制御を行っている事に注意  まず、I/Oリソースに関して全く制御していない状況で、I/Oの速度を計測してみる。I/Oの速度計測にはOracleが提供しているDBMS_RESOURCE_MANAGE