本文書に関する指摘については、原文著者のTanel Poderさんではなく、渡部まで御連絡お願いいたします。
注意事項
- 自動翻訳に手を加えたレベルの翻訳と理解してください
- 意味をとりやすくするために追加した箇所については、《…》で囲っています。
- 訳がわからない、または、自信がない箇所は★をつけています。
日本語訳:渡部 亮太 (WR at Csus4 dot net)
履歴
- 2013-12-03: 初稿up
Advanced Oracle Troubleshooting Guide, Part 2 : 魔法は必要ありません、体系的なアプローチで成しえるものです
問題を診断するための2通りの方法があります。
- 一般的に疑われる点をチェックし、該当するものを見つけられることを望む
- 以下で説明ような体系的なアプローチ
一般的に疑われる点をチェックし、該当するものを見つけられることを願う
最初のアプローチは、(特定領域/技術と問題が発生したコンテキスト/環境についての両方)のこれまでの経験に依存しています。たとえば、もし患者が胸の痛みを訴えて病院に来たならば、医師(および患者)のためにそれは間違いなく、患者に関する関連する背景情報を知ることは有益である – すなわち、コンテキスト。患者は10フィートのはしごから落ちていたなら、骨折した肋骨を探すことが、より適切になるでしょう。一方、患者が長年??の喫煙していて、痛みが始まったときソファでテレビを見ていた場合、おそらく、心電図から開始することがより適していると思います(私は人間の体は非常にどのように機能するかについての専門家ではないことに注意してください。誰もがすぐに本当の医師に送信し★、あなたにその胸の痛みに文句を言う必要があります!)
とにかく、あなたが5年間フルタイムであるデータベースを管理してきたなら、あなたはおそらく特定の問題が発生したとき、どこを見るべきかすぐにわかるに違いない。ここで、「すぐに何を変えるべきかわかる」ではなくて、「すぐに見るべき場所《がわかる》」と書いたことに注意してください。問題の根本原因を特定するため、これまでの経験を使用することは、(繰り返し)非常に高速にあなたがそのソリューションを使うことができる完全に有効なアプローチである。 – しかし、その方法は、あなたがその技術とその特定の環境についての問題を解決するためのたくさんの過去の経験を持っている場合(つまり、コンテキストを知っている場合)にのみ、うまく機能する。ここでの大きなリスクは、「古く、そしてよく知られた問題」と同様の症状である「新しい」問題が現れた場合、間違った問題を修正してしまうことになる可能性があることです。そして、その解決策が機能しない場合には、昨年の別の問題を解決した、ある解決策を試し続けることになる。そして、問題が解決しない場合、その後もサイクルは続き、かつて有用だったあまり関係なさそうな修正を見つけ出し、それらを適用することになります。それで、google検索して、他の人が経験した問題のために提案されたソリューションをなんでも試すことに訴える。
私たちは、 絶望的なスイッチフリッピング状態(Desperate Switch Flipping )★で終わっている。通常、これはさらに大きなスイッチを反転することにつながる。Oracleのセッション/インスタンスパラメータから始まり、ランダムにSQLヒントを追加し、サーバを再起動し、データベースやオペレーティング・システム、ハードウェアをアップグレードし・・・ たいてい幸運をもたらさない。これは時間の無駄であり、私たちの問題を解決せず、さらに多くのトラブルを引き起こす可能性すらあります。これは良くありません。一般的に疑われる点をチェックすることは、一般的な繰り返し発生する問題の解決に役立つことがあります。(ねぇ、優れた専門家だったら、何度も何度も修正するのではなくて、問題を避けるべきなんじゃない?)しかし、一般的に疑われる点をチェックすることと、DSF状態に陥ることの間に線を引くことは、非常に重要である。Oracle-Lの誰かに起こったように見えるように★
引用:
「私は、私は顔が真っ青になるまで、Statspackレポートを最高レベルで実行しました。私はトレースを実行しました。私は、イベントを設定しました。しかし、私はまた、私の直感的な結論をバックアップするために、事実と問題を解決するために直感を使用することが多い傾向があります。直感的な自然が私とだから、オラクル社カスタマ?サポート?センターにこのようなもののすべてを提供した後、彼らは途方に暮れていた彼らは、別の解決策を持っていなかったので、まあ、それは、原因として腐敗を見て非常に切望していた。」
(ところで、GajaがCTD とともに始めた病理学的なDBAの問題のリストに、DSF状態を追加することが適切だと思う)
問題を診断するもう1つの方法は、 体系的なアプローチに従うことです。それは、コンピュータがどのように動作するかの知識に基づく適切な方法論です。
体系的なアプローチに従う
個人的には、そのシステム(または類似のシステム)における問題を診断した私の (sic!)経験に基づいて、一般的に疑わしい問題をチェックすること、多くの場合、迅速なMy Oracle Support(Metalink)の検索を行うこと★を許しています。
しかし、これがすぐに根本的な原因を明らかにしない場合、関心を持つタスクのダイナミクスを測定開始することから、 体系的になります。《体系的なアプローチをとるように方針変更する。という意味かな》私はランダムに暗闇を打つこと、検索エンジンに現れるインターネットの記事に基づいて、DSFを行うことを始めません。
それは、Oracleの世界では体系的であることが簡単です。これは主に次の理由です:
- コンピュータおよびコンピュータシステムは、決定論的である – 同じ入力条件のセットに対して、まったく同じ出力条件のセットを常に生成する。人間の相互作用、分散システム、可能な低レベルのバグや破損が、大規模なコンピュータシステムを非決定論的にすると主張する人もいるかもしれない。しかし、問題のある特定のタスクのトラブルシューティングを行うときには、システムのインタラクションにおいて、タスクが直面している直接のポイントだけを特定すれば十分である。ここはinstrumentationの出番です。
- Oracleはwell-instrumented《診断機能が充実しているぐらいの意味か》である – タスクの問題を絞り込むことが容易です。様々なトレース、Oracle wait interface、統計カウンタ《統計情報》。問題が発生したときにOracleが何をしているかをよく理解できる。
- コンピュータ?ソフトウェアはブラックボックスではありません – Oracleも例外ではない。ソフトウェアのどの部分も、物理的には関数にクラスタ化された、CPUが決定論的な方法で実行する一連のコンピュータ命令にすぎない。(私はここれ非常に決定論的と言うことを避けた。あなたは、多かれ少なかれ決定論的システムを持つことができないので、それが確定的かのどちらかです★)
そして、コンピュータのCPUは、それらのマシンコードの実行において、間違いなく決定論的である。だから、(このシリーズの以前の記事)からブログを始めたように)セッション統計およびwait interfaceだけでは不十分であっても、Oracleがいるカーネルコードパスの箇所を追うことは非常に簡単です。
私は通常、ハイレベルから診断し、問題のあるタスクを計測することから始めます。その結果に基づいて、どこをドリルダウンするか、どこでデータの次のセットを測定するか、どの特定の領域に重点を置くかを決定します。そのデータを見て、適切な場所で再び測定します。たいてい、根本的な原因にはステップバイステップに近づいてゆきます。
で、どうやって実際のありようをどうやってやるのか★?最善の方法はreal lifeからいくつかの例を提供することだと、私は考えます。Oracleで発生する可能性のある問題の様々な種類がありますが、問題の最も複雑な(そして面白い)タイプの一つは、パフォーマンス上の問題です。そして、これが私が始めるところです。でも、私は、単純なパフォーマンスの問題から始めます – 単一の識別可能な Oracleセッションで発生したパフォーマンスの問題
ケーススタディ1:セッションがハング – 待機なし、CPU使用なし
私は、しばしば、セッションが明らかにハングし、しばらくの間応答しない問題に対処しなければなりません。たいてい、ロックを待機していたり、ネストされたループをやって(デカルト)が数百万行の上に結合しする暴走した実行計画のような、シンプルな状況です。そのような場合は、解決するのは簡単です。しかし、これから説明する事象は、かなり興味深いものでした。(Oracle 10.1 on Solaris 8 Sparcの64ビット)
1) そのセッションについて、V$SESSION_WAITをチェック
私の小さなスクリプトsw.sql (sw = Session Wait)を用いて、そのセッションについて、V$SESSION_WAITを問い合わせた。私のスクリプトは、読みやすくするために、いくつかのデータをフォーマットしているので、V$SESSION_WAITの情報と同様に、プレーン "生"クエリの出力を追加しました
SQL> select state, seq#, event, seconds_in_wait from v$session_wait where sid = 197;
STATE SEQ# EVENT SECONDS_IN_WAIT
??????- ???- ?????????? ?????
WAITED KNOWN TIME 63 SQL*Net message from client 1505
SQL> @sw 197
SID STATE EVENT SEQ# SECONDS_IN_WAIT P1 P2 P3
???- ??- ??????? ??- ????? ???? ???- ???-
197 WORKING On CPU / runqueue 63 1514 1413697536 1 0
両方のクエリの出力から、Oracleは、セッションが何かを待っている状態(statusがWAITINGではなくてWAITED)ではないと考えていることがわかります。よって、明らかに直近の1500秒はCPUの上にあります《CPUを使用しています》。このような場合、私は常に、OSが言わなければならないことを確認します。
OSツールは、プロセスの状態により正確に把握できるだろうからです。(そして、その理由はOSツールが直接OSのプロセステーブルを照会している点です。OracleのV$SESSION_WAITが、Oracleによりデータが移入されている一方で)
2)OSレベルからリソースの使用率を確認する
SQL> select spid from v$process where addr = (select paddr from v$session where sid = 197);
SPID
????
9597
$ prstat -p 9597
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP
9597 oracle 1145M 1070M sleep 59 0 0:00.00 0.0% oracle/1
$ ps -flp 9597
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
c S oracle 9597 1 0 40 20 ? 146564 ? 11:09:44 ? 0:00 oracleXXXXXX01 (LOCAL=NO)
prstatとpsの出力の両方は、このプロセスが1500秒間activeな状態にあったとしても、sleep中であり、注目すべき程度にはCPU時間を使用していないことを示しています。
3) プロセスがsleepしているOracleカーネルコードパスの場所を確認する
上記の2段階の診断により、このセッションは、生存期間の大部分何かを待っていることが既に証明された。そして、Oracleのwait interfaceがこの待機を記録することに失敗しています。よってV$SESSION_EVENTなどを見てももはや意味がありません。よって、ソースに直接アクセスし、何が起こっている取得することにしましょう。
私はソースコードを持っていない(そして、過去持っていたこともない)ので、ソースに移動するというのは、ソースコードを見るという意味ではない。ではなくて、プロセスがstuckしているという仮説と荒い推測の代わりに、それがスタックしている場所に行ってみて、確認しましょう。ということを意味しています。
どんなデバッガもこの情報を提供できます。また、SolarisとLinuxでは便利なpstackというユーティリティがあります。
$ pstack 9597
9597: oracleXXXXXX01 (LOCAL=NO)
ffffffff7c9a7854 sigsuspend (ffffffff7fff6d90)
ffffffff7c956d2c _libc_sleep (0, 5, 0, 0, 0, ffffffff7fff6f21) + f8
0000000100cc0188 qm_init_uga_helper (380028000, 380028, 3ba048b68, 380000, 380028000, 380028000) + 6c8
00000001002d4808 rpiswu2 (0, 104556000, ffffffff7fff70d8, 2, 104556418, ffffffff7fff7a80) + 1a8
0000000100cc5af0 qm_run_as_ksys (ffffffff7fff761c, 100cbfac0, ffffffff7fff7541, 1042dbd80, 1042db000, 1042db) + b0
0000000100cc0314 qm_init_uga (3ee8, 1042969f0, 104296000, 104296, 100cbf000, 100cbf) + 14
0000000100d2a5f4 qmeGetResRelByHdl (105000, 0, 105140578, 21, 0, 0) + 54
0000000100cac7e0 qmtkLookupSchemaOIDPath (e, 1428, ffffffff7fff7fb0, 105069b28, 10506ae00, 104400) + 180
0000000100cac5cc qmtkLookupSchemaOID (105068700, 6, d, ffffffff7fff87d8, ffffffff7fff7ce4, 0) + ac
00000001002ba9b0 qmtLookupSchemaElement (104556, ffffffff7b3410d8, d, ffffffff7b340090, 7, ffffffff7fff87d8) + 30
000000010309a834 qmu_preparse_xml2 (42400, 3c0bfcf49, d, 0, e, ffffffff7fff7fb0) + 454
00000001030bccac qmxtgGetUrlAndElNameCS (c, ffffffff7b9701f8, ffffffff7fff87e8, 10501dba8, 10501dba8, ffffffff7fff8808) + 14c
00000001030bd0e0 qmxtgCreateFromLob (105068700, ffffffff7bb61e88, ffffffff7fff87e8, 0, 1a, ffffffff7b9701f8) + 180
0000000102649ca4 qmxtkCreateFromLob (ffffffff7fff9fe8, ffffffff7bb61e88, 0, ffffffff7fff8938, ffffffffffffffff, 0) + 164
0000000102649d30 qmxtkCreateFromClob2 (0, 0, 0, ffffffff7bb69960, ffffffffffffffff, 0) + 50
000000010264ae2c qmxtkConsFromClob (ffffffff7bb69980, 0, ffffffff7bb69960, 0, 0, 0) + 4c
0000000103a21b3c spefcpfa (0, 10264ade0, ffffffff7bb69828, ffffffff7fff9088, ffffffff7bb69960, 103a216a4) + 4dc
00000001039d8a70 spefmccallstd (ffffffff7fffa058, ffffffff7fff9b90, ffffffff7fff9c60, ffffffff7fff9bd0, 2c, ffffffff7fff9bd0) + 1f0
00000001038f42c8 peftrusted (ffffffff7fff9bd0, 104556000, ffffffff7fffac78, ffffffff7fffa058, 105068700, ffffffff7fff9c60) + 88
0000000103a9c678 psdexsp (380007, 104556, ffffffff7fff9278, 10506b000, 10506b, 105068860) + b8
00000001002d4808 rpiswu2 (0, 104556000, ffffffff7fff9438, 2, 104556418, ffffffff7fff98c8) + 1a8
0000000103a9c3c0 psdextp (10506a000, 103a9c000, 0, 0, a, 9) + 180
00000001038f3eac pefccal (ffffffff7fffac78, ffffffff7fffa058, ffffffff7fff9c60, ffffffff7ba5e050, 105068700, 100b0aa80) + 12c
00000001038f3c14 pefcal (ffffffff7fffa058, 1, 105068860, 4004, 4326, 4000) + 94
000000010377407c pevm_FCAL (ffffffff7ba5e050, 3ba9eed48, ffffffff7ba5e0b8, 3ba9f0e18, 1, ffffffff7fff9fe8) + 7c
00000001037400cc pfrinstr_FCAL (ffffffff7ba5e050, 3ba9f0bde, ffffffff7ba5e0b8, 10457d, 104400, 3ba9f0be4) + 4c
00000001037362c8 pfrrun_no_tool (ffffffff7ba5e050, 3ba9f0bdc, ffffffff7ba5e0b8, 10457c9d8, 2001, 2001) + 48
00000001037372d0 pfrrun (ffffffff7ba5e0b8, 200000, 0, 200000, ffffffff7ba5e050, 3ba97022c) + 2f0
0000000103783374 plsql_run (ffffffff7ba6e4a0, 1, 0, ffffdfff, ffffffff7fffac78, 0) + 274
0000000103722554 peicnt (ffffffff7fffac78, 105068860, 6, ffffffff7fffaae8, 41d8, 1050685e8) + d4
000000010327b784 kkxexe (105000, 104000, 105068, 104296000, 1050685e8, ffffffff7ba5e050) + 284
0000000101ad0228 opiexe (4, ffffffff7ba3a6a8, ffffffff7fffb6c0, 0, 0, ffffffff7bb70420) + 33c8
0000000101a4c0a8 kpoal8 (40008, 1, ffffffff7fffe450, 0, 0, 3) + 648
00000001002d0058 opiodr (14, 10506ae10, 10434ce70, 10506a, 105000, 104000) + 598
0000000102cded94 ttcpip (105071450, 18, ffffffff7fffe450, ffffffff7fffd748, 104229c98, ffffffff7fffd744) + 694
00000001002cd3e8 opitsk (1002cf000, 1, 0, ffffffff7fffe5a8, 105071450, 105071458) + 428
0000000101aaf564 opiino (105070000, 105000, 3c0a60c98, 105000, e4, 105070290) + 404
00000001002d0058 opiodr (4, 10506ae10, 10434c920, 10000, 105071, 105000) + 598
00000001002cc174 opidrv (0, 4, 10506a, 105071450, 0, 3c) + 354
00000001002c9828 sou2o (ffffffff7ffff278, 3c, 4, ffffffff7ffff258, 104aa6000, 104aa6) + 48
00000001002a7b34 main (2, ffffffff7ffff358, ffffffff7ffff370, 0, 0, 100000000) + 94
00000001002a7a7c _start (0, 0, 0, 0, 0, 0) + 17c
これは、サーバープロセス9597の現在の状態の完全なスタックトレースです。
最初は理解しにくく感じられるかもしれませんが、実際には簡単です!下から読み始めてみましょう:
- 一番下の行から、(通常UNIXのシステムコール folk()+ exec()によって)_start()関数が呼び出されたこと、その関数の実行は、関数の開始アドレスから0x17cバイトのところに到達していること、そこはリスト内の次の関数を読みだしているところであることがわかる。関数の開始アドレスが関数名のすぐ前、出力の第1列で指定されていることに注意してください。
- 今回の場合は、main()が次の関数として呼ばれ(ちょっと慣れてきた?;-))、sou2o()を呼び出したとき、プログラムの実行は最初から0x94バイトに達する。
- sou2oは、先頭から0x48バイト進んだところに達した後、opidrv()を呼んでいる。
- opidrv(Oracleのプログラム?インタフェースドライバ)は、その開始から0x354バイト進んだところに達した後、opiodrを呼ぶ。括弧内の数字は、呼び出された関数に渡される引数であることに注意してください。しかし、完全かつ完全に正確でない場合があります。これらはスレッドスタックストレージから読み込まれるものですが、いくつかのパラメータがCPUレジスタで渡されるかもしれず、これらその場合スタックには一切情報が記録されないので。
- opiodrは、その開始から0x598バイト進んだところに達した後opiino()を呼ぶ。0x598バイト分の命令が実行される価値を持つことを意味するのではないことに注意してください。他に多くの関数を呼び出し、関数で処理を実行した後に帰ってきたのかもしれない。また、関数内部で何度も行きつ戻りつしていたかもしれない(例えば、ループ)。
- opiinoがopitsk()を呼んだ。 ここは、メインの低レベルのタスクディスパッチが行われる場所である。実行すべき処理がない場合には、通常Oracleのネットワーク処理コードを持つ"n"から始まる関数を待機している、opikndf2で待機する。
ネットワーク処理関数がリターンしたとき、通常はクライアントから送信されたデータを取得できているので、それに応じてopitskは適切な処理関数を呼び出す。この処理は、通常、上記のスタックトレースで見られるように、ttcpipになる。
- その名前にもかかわらずttcpip()は、TCP/IPを直接処理しません。実際にはTwo-Task Common PIPe read/write(TTC pipe)を意味します。名前が示すように、これは「内側」のサーバーコードと世界に公開される「外側」との間にある分離層およびゲートキーパーです。Oracleカーネルへのシステムコールインタフェースのように考えることもできます。多くの健全性チェックや変換が、TTC層で行われます。
- いくつかの行をスキップすると、リクエストを実行するめのOPI関数であるopiexeを見ることができる。(それらは、SQLトレースにおけるEXECの行に変換される。ちなみに、opiparとopifch関数は、PARSEとFETCHに対応している)
- 引き続き、PL/SQL関連の関数であるpeicnt、plsql_runとpfrrunを見ることができる。
そう、このプロセスは、PL/SQLを実行しているに違いない。 - 引き続き、rpiswu2関数を見ることができる – RPIはRecursive Program Interfaceの略で、再帰SQLや自律型トランザクション、PL/SQLからのSQLの実行し、その逆などなどなど・・・のような再帰呼び出しをセットアップするために使用される。基本的に、RPIの呼び出しは、現在の呼び出しが完了する前に実行する必要のあるコールのための、変数やステートオブジェクトなどの独立したコンテキストをセットアップする。
- 引き続き、peftrusted()コールを見ることができる。これは興味深いものです。信頼されたモードで外部ライブラリを呼び出すことを許可する。それは、すでにロードされている(か、ロードされる)、(EXTPROCによってライブラリ関数を呼び出すことではなく)Oracleサーバー?プロセスのアドレス空間内を意味する。OracleのXMLTypeのタイプとORACLE_LOADER&ORACLE_DATAPUMP ODCIカートリッジは、この機能を使用しています。
- 引き続き、qm*コールを見ることができる。これらはXMLデータ型とXMLスキーマを処理する。
- 引き続きスタックのトップに向かうと、UGAの初期化関連の関数と、ksysとして実行される予定のコードを示す、ある関数を見ることができる。(私はksysか何を意味するかわからないが、qm_run_as_ksys関数が再びrpiswu2を呼び出しているため、Oracleが昇格した特権モードでコードを実行するために別のコンテキストを設定する方法についての良い例です。)
- そして、0x6c8バイトだけqm_init_uga_helper関数に入ると、何か違う出来事を見ることができる – この関数は、次の関数_libc_sleep呼び出し、今度はsigsuspend()システムコールを発行していた。
(0x000000010xxxxxxx・・・と?0xffffffff7c956d2cを対比して)最初の列から、これらの関数はプロセスのアドレス空間内の別の場所に存在していることがわかる。では何が起こっているのだろうか?
このような関数の開始アドレスの違いは、プロセスのアドレス空間を調べることによって説明できる。
$ pmap 9597 | grep -i ^000000010
0000000100000000 81016K read/exec /apps/oracle/product/10.1.0.3/bin/oracle
000000010501C000 864K read/write/exec /apps/oracle/product/10.1.0.3/bin/oracle
00000001050F4000 432K read/write/exec [ heap ]
$ pmap 9597 | grep -i ^ffffffff7c9
FFFFFFFF7C900000 728K read/exec /usr/lib/sparcv9/libc.so.1上記の出力から、Oracleバイナリ自体は、プロセスのアドレス空間におけるアドレス0x100000000にマッピングされていることがわかる。
- libc.so.1はffffffff7c900000にマッピングされており、合計サイズが728KBです。これは、_libc_sleep機能がライブラリの中間のどこかであることを意味している。(アドレスffffffff7c956d2c -56d2cはおよそ355Kです)ライブラリイメージの開始アドレスから相対的な、その関数の開始アドレスは、 nmユーティリティを使用して確認できます。
$ nm /usr/lib/sparcv9/libc.so.1 | egrep "Size|_libc_sleep"
[Index] Value Size Type Bind Other Shndx Name
[228] | 355380| 396|FUNC |LOCL |0 |9 |_libc_sleep
したがって、このスタックを読んだ結果、Oracleプロセスが実行している場所についての決定的な証拠を得た。stuckしている。 – あるXMLコードから呼び出されたsleepシステムコールにおいて。そして、この処理は、Oracleのwait interfaceによって記録されていない。これは間違いなく異常である。単なるパフォーマンスやユーザコードの問題ではない。スタックトレースを読むことは非常に役に立つ。
知識で武装すると、これは、単なるユーザプロセスの記録されないI/O関連の待機や、CPU上でのスピンではない《と感じられた》。スタック内のrpiswu2 / init_uga / _libc_sleepコールを見た後、私は、メモリ割り当てやシステムライブラリの呼び出しに関連したものでないか、疑問に思い始めた。(そう、 ここが、これまでの経験が再度kickしたところです)。
私は、Oracleインスタンスを起動するために使用されるUNIX環境変数を見てみた。そこにそれがあった – LD_LIBRARY_PATHにおいて、$ORACLE_HOME/lib32ディレクトリが$OH / libの前に来ている。これがいくつかのXMLDB機能が失敗する原因であった。
(おそらく、64ビットのアドレス空間へ32ビット?ライブラリーをロードしようとして、何かを台無しにしていた。多分、共有オブジェクト?ライブラリ関数のアドレスがロードされるPLTセクションを処理し★)
この例で、スタックトレースをチェックすることは、環境変数の問題を私に直接示唆するものではなかった。しかし、ハングに関する他の多くの原因を、すぐに排除するのために役立った。IOが記録されないハング、別のプロセスからのIPCポスト欠落してウェイクアップされていない、など。
また、スタックの先頭に記録されたOracleカーネル関数は、本来実行すべき処理について示唆を与えてくれます。(別のコール環境をセッティングするRPI、UGAの初期設定 – メモリ割り当てなどを意味するでしょう)。
よって、スタック?トレースは、Oracleインストルメンテーション《診断機能》が提供されないところで非常に役立ちます。スタックトレースに関する重要なことは、究極のコンピュータの現実を見ることができる。Oracleサーバー?プロセスが何をしているかを確認するための最も正確な場所を見ることができるということです。《Oracleの》統計または待機イベントは、スタックトレースの精度と信頼性を負かすことはできません。なぜなら、その情報は、「ソース」 – ハードウェアのABI(アプリケーションバイナリインタフェース)標準により構成されるスレッドのスタックメモリ構造 – から直接得られたものであるからです。
スタックトレースの取得の解釈には(いつものように)いくつかの問題があること、スタックトレースが常に正確な状態を示さない場合もある(例えば、スタックの破損スタック)ことに注意してください。おっと、今気づいて驚いたのだけど、既に午前1時だ。それについては次回のブログで 😉
結論
So, where am I getting at?★
さて、私はちょうど始めたところだ。スタックトレースを使用して、ASSMのパフォーマンスのバグを診断する私の経験のいくつかの例があります。ブログを書く時間があるとき、高度で正確なトラブルシューティングのために、スタックトレースという道具がどれだけ重要であるか、明らかになるだろう。Oracle / OSのインストルメンテーション《診断機能》が正確な状態を表示することができれば、スタックトレースは全く必要とされないかもしれない 。あるいは、このようなツールは、常に必要とされないかもしれない – あなたはトラブルシューティングしているシステムにおける、深刻な過去の経験がある場合?
(表Tのコメント列が'blah'であるバインドピークによる悪い実行計画と、毎週の月曜日の朝、誰か火消しで戦った?★;-) )
So, where I’m getting at is stated below★ ? 下の2つ目のポイントについての詳細記事を書くつもりである。
- 一般的に疑わしい点をチェックすることは、非常に早くあなたをそこに到達させる★かもしれない。
- 体系的なアプローチに従うことは、あなたをそこに到達させる★ものだ 。
参考資料
Metalink Note 175982.1 ORA-600 Lookup Error Categories ( many Oracle kernel function prefixes are documented there )
Metalink Note 453521.1 ORA-04031 “KSFQ Buffers” ksmlgpalloc ( some common Oracle kernel functions are documented there )