私のメインの本番RACデータベースでは、速度が低下している期間があり、システム全体での主要な待機イベントは「カーソル:ピンSがXで待機」です。イベントは行ったり来たりしますが、私は時々それを見ます。だから私はこれの底を取得する必要がありました。これはRACの問題ではないことに注意してください。このイベントは、単一インスタンスのデータベースでも簡単に確認できます。 Oracle RACデータベースの複数のインスタンスでこれが見られるのは、同じアプリケーションからの複数のセッションがインスタンス間で分散していて、すべて同じことを行っているため、すべて同じ問題が発生しているためです。
まず、待機イベントとは何ですか? 「cursor:」待機はいずれも、SQL領域の共有プールのボトルネックです。ずっと前に、共有プールのこの部分はラッチによって保護されていました。しかし、共有プールの多くの領域の場合と同様に、Oracleは現在ミューテックスを使用しています。保護メカニズムの変更により、新しい待機イベントが発生しました。
この特定の待機イベントの場合、共有ピンが必要なカーソルがありますが、別のセッションがその排他的ミューテックスを解放するのを待つ必要があります。カーソルを解析しようとしています。ただし、別のセッションが同じミューテックスを保持しているため、解析できません。
このイベントを待機しているセッションには、主に3つの原因があります。
- 高ハード解析
- SQLステートメントの多数のバージョン
- バグ
残念ながら、この待機イベントに関連するバグがいくつかあります。私が見たもののほとんどは11.2.0.4または12.1.0.1で修正されているため、バージョンが遅れている場合は、最新のOracleバージョンの1つにアップグレードすることを検討してください。
それでは、問題の原因を特定するために例を見ていきましょう。そのために、次のクエリを使用しました:
select s.inst_id as inst, s.sid as blocked_sid, s.username as blocked_user, sa.sql_id as blocked_sql_id, trunc(s.p2/4294967296) as blocking_sid, b.username as blocking_user, b.sql_id as blocking_sql_id from gv$session s join gv$sqlarea sa on sa.hash_value = s.p1 join gv$session b on trunc(s.p2/4294967296)=b.sid and s.inst_id=b.inst_id join gv$sqlarea sa2 on b.sql_id=sa2.sql_id where s.event='cursor: pin S wait on X';
これを本番RACデータベースの1つで実行すると、次の出力が得られます。
INST BLOCKED_SID BLOCKED_USER BLOCKED_SQL_ID BLOCKING_SID BLOCKING_USER BLOCKING_SQL_ID ---- ----------- ------------ -------------- ------------ ------------- --------------- 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g>
最初に注意することは、ミューテックスはOracleRACデータベースのそのインスタンス内にのみ存在するということです。シングルインスタンスデータベースの場合、上記のクエリは引き続き機能します。 Oracle RACの場合、このクエリの出力には、問題が発生しているインスタンスが表示されます。
上記の例では、セッション723がセッション1226によってブロックされています。セッション1226はセッション1796によってさらにブロックされています。3つのセッションすべてがSQL ID cn7m7t6y5h77gで同じクエリを発行していることに注意してください。 。
SQL IDがわかったので、V $ SQLを簡単に照会して、問題に関係するSQLステートメントを判別できます。このクエリを使用して、より多くの情報を取得しました。
select sql_id,loaded_versions,executions,loads,invalidations,parse_calls from gv$sql where inst_id=4 and sql_id='cn7m7t6y5h77g';
V$SQLのクエリからの出力は次のとおりです。
SQL_ID LOADED_VERSIONS EXECUTIONS LOADS INVALIDATIONS PARSE_CALLS ------------- --------------- ---------- ---------- ------------- ----------- cn7m7t6y5h77g 1 105 546 308 3513
これで、このクエリのSQL領域にバージョンが1つしかないことがわかります。そのため、すぐに、潜在的な問題領域の1つを排除しました。今後のブログ投稿では、SQL領域に多数のバージョンがあるクエリについて説明します。しかし、それは今日の私たちの問題ではないので、先に進みます。
上記から、非常に多くの解析呼び出しがあることは明らかです。クエリは105回しか実行されていませんが、3513回解析されています。うわぁ!無効化の場合の高い数値は、おそらくこれにも関係しています。
この例では、問題が何であるかがわかりました。これはアプリケーションの問題です。アプリケーションがクエリを解析しすぎています。そこで、これを開発に送り返し、アプリケーションコードを掘り下げます。過剰解析の通常の理由を調べる必要があります。
バージョンの数が少なく、過度の解析/無効化/ロードが問題ではなかった場合は、バグを疑ってOracleサポートにSRを提出します。