私は数週間追跡していたバグがあります。しかし、なぜこのようなことが起こるのかは、Oracle - プロシージャコール間でデータ/状態が失われている間違った断続的なエラー
私は非常に大きなOracleパッケージ(約4,100行のコード)を持っています。私はいくつかの手順を呼び出しています。しかし、プロシージャコールの間にデータが失われているようです。
失われているデータは次のとおりです。
dpmethodstate varchar_state_local_type;
まず、私は、このプロシージャを呼び出す:
PROCEDURE delivery_plan_set_state (
messages OUT ReferenceCursor,
state IN varchar_state_local_type
) AS
BEGIN
logMessage('state COUNT is: ' || state.COUNT);
dpmethodstate := state;
FOR I IN 1..dpmethodstate.COUNT LOOP
logMessage(dpmethodstate(I));
END LOOP;
logMessage('delivery_plan_set_state end - dpmethodstate count is now ' || dpmethodstate.COUNT);
OPEN messages FOR SELECT * FROM TABLE(messageQueue);
messageQueue := NULL;
END delivery_plan_set_state;
私は状態を渡し、単一の文字列の有効な配列です。手順が終了すると、dpmethodstate
にCOUNT
が1
であることをログで確認できます。
次に、私はこのようになりますexecute_filter
プロシージャを呼び出す:
PROCEDURE execute_filter (
--Whole bunch of OUT parameters
) AS
--About 50 different local variables being set here
BEGIN
SELECT TO_CHAR(SYSTIMESTAMP, 'HH24:MI:SS.ff') INTO TIMING FROM DUAL;
logMessage('[' || TIMING || '] execute_filter begin');
logMessage('a) dpmethodstate Count is: ' || dpmethodstate.COUNT);
--Rest of procedure
しかし、今回dpmethodstate.COUNT
が0
です。私がdelivery_plan_set_state
から設定した値は消えました!あなたが見ることができるように
proposed
delivery_plan_set_state end - dpmethodstate count is now 1
[21:39:48.719017] execute_filter begin
a) dpmethodstate Count is: 0
、dpmethodstate
は、プロシージャ・コールの間で迷子になった:私は私のログを見てみると
が、それは次のようになります。
- このパッケージでは他に何も
delivery_plan_set_state
以外dpmethodstate
の値を設定することが可能ではありません。注意すべき点がいくつかあります。そして私は他の誰もそれを呼んでいないのを見ることができます。 - 私のクライアントサイドのコードはC#で書かれており、2つのプロシージャコールの間にはあまり発生しません。
- これはおそらく100回に1回発生するため、追跡またはデバッグすることは非常に困難です。
まず、このような問題をデバッグするにはどうすればよいですか?私ができるロギングはもうありますか?また、Oracleはプロシージャー呼び出しの間の状態をどのように維持し、何かが断続的に行うことができますこの状態をリセットしますか?どんなポインタであれ大いに感謝します!
さて、私はちょっとコネクションプーリングと関係があると思っていました。 Webサーバーは.NET Entity Frameworkを使用していますが、どのように(またはドライバ)接続をプールするのかはわかりません。しかし、2回の呼び出しはミリ秒間隔で行われ、同じHTTP要求で行われます。 .NETは "ちょっとこの接続を捨てて別のものを使う"と言うでしょうが、おそらく彼らはいくつかの奇妙な最適化ロジックを持っています。私はsidとシリアル番号を記録するあなたのアイデアは間違いないと思う、私はこの最初の事を明日試してみよう! –
これは私のローカルデータベース上で動作することを確認しましたが、プロダクションでv $ sessionに対してSELECT権限を与えることに決して同意しませんでしたので、この方法を使用して問題を追跡することはできません。私はこれがこの質問のための最良の答えだと思う! –
@MikeChristensen - 'v $ session'を照会するのではなく、' sys_context( 'USERENV'、 'SID') 'と' sys_context( 'USERENV'、 'SESSIONID')をログできます。まったく同じことではありませんが、異なるセッションがあるかどうかを確認するという同じ目標を達成する必要があります。 –