[seasar-dotnet:2149] Re: S2Dao.NetでORA-01002が稀に発生する現象について(再送)

K.Ohmori [E-MAIL ADDRESS DELETED]
2012年 4月 13日 (金) 15:45:34 JST


小谷様

お世話になっております。大森です。
ご回答ありがとうございます。

>>・VMが3機あってそれぞれがDBサーバとのことですが、
>>1回の処理でA,B,CそれぞれのDBを更新しているでしょうか?  
>>(ログを拝読する限りではデータソース「001」しか使われていないようで
>>すが念のため)  
>>(複数のデータソースを使用している場合、トランザクションはデータソース
>>ごとに別々に発行されます。そのこととマテリアライズドビューによる同期が
>>何か問題を起こしている可能性を想定しています)

お察しのとおりです。
エラーが発生している該当の登録処理で更新しているDBは1つになります。
(システム全体でもフェーズコミットを行っている個所はありません。)
マテリアライズドビューに関しましては、該当の登録処理には使用しておりません。

>>・各DB用のTransactionSettingで行っている拡張は
>>「TypicalTransactionSetting」をDataSourceNameプロパティだけoverride、
>>のような形でしょうか?
>>それともSetupTransactionメソッドなど他のメソッドも拡張されているで
>>しょうか?

AbstractTransactionSettingを継承して拡張設定を実装しております。
DataSourceNameのOverridesに加え、SetupTransactionを
Overridesしております。
ご承知の通り、DBサーバは3機あるのですがそのうち2機はスキーマが全く同じ
なので3機のDBサーバに対して、2つの拡張設定を実装しています。
(仮にDBサーバAとB1、B2とします。)
システム起動時のログイン情報によってB1、B2を切り替えてTransactionContext
を生成するという想定で実装しております。
ソースを以下に添付いたします。

/** AのTransactionSetting **/
Public Class ATransactionSetting
Inherits AbstractTransactionSetting

Public Overrides ReadOnly Property DataSourceName() As String
Get
Return "A"
End Get
End Property

Protected Overrides Sub SetupTransaction(ByVal dataSource As
Seasar.Extension.ADO.IDataSource)

' TransactionContext
_transactionContext =
TransactionContextCreator.GetTransactionContext(dataSource)
Dim txContext As TransactionContext = DirectCast(_transactionContext,
TransactionContext)

' TransactionContextを使用するデータソースにも設定
Select Case dataSource.GetType().Name

Case GetType(SelectableDataSourceProxyWithDictionary).Name
DirectCast(dataSource,
SelectableDataSourceProxyWithDictionary).SetTransactionContext(txContext)

Case GetType(TxDataSource).Name
DirectCast(dataSource, TxDataSource).Context = txContext

End Select

' TransactionInterceptor
Dim handler As LocalRequiredTxHandler = New LocalRequiredTxHandler()
handler.Context = txContext
_transactionInterceptor = New ATransactionInterceptor(handler)
DirectCast(_transactionInterceptor,
ATransactionInterceptor).TransactionStateHandler = txContext

End Sub

Public Class TransactionContextCreator

Private Shared _transactionContext As TransactionContext = Nothing

Public Shared Function GetTransactionContext(ByVal dataSource As
IDataSource) As ITransactionContext

If _transactionContext Is Nothing Then

_transactionContext = New TransactionContext()
_transactionContext.DataSouce = dataSource
_transactionContext.IsolationLevel = IsolationLevel.ReadCommitted

End If
Return _transactionContext

End Function

End Class

End Class
/** Aここまで **/

/** BのTransactionSetting **/
Public Class BTransactionSetting
Inherits AbstractTransactionSetting

Public Overrides ReadOnly Property DataSourceName() As String
Get
Dim ds As String = ""
Try
' TODO: ログインに対応したコードから取得
Dim user As clsUser = clsGrobals.LoginUser
If user IsNot Nothing Then
ds = user.Code
End If
Catch ex As Exception

End Try
Return ds
End Get
End Property

Protected Overrides Sub SetupTransaction(ByVal dataSource As
Seasar.Extension.ADO.IDataSource)

' TransactionContext
_transactionContext =
TransactionContextCreator.GetTransactionContext(dataSource)
Dim txContext As TransactionContext = DirectCast(_transactionContext,
TransactionContext)

' TransactionContextを使用するデータソースにも設定
Select Case dataSource.GetType().Name

Case GetType(SelectableDataSourceProxyWithDictionary).Name
DirectCast(dataSource,
SelectableDataSourceProxyWithDictionary).SetTransactionContext(txContext)

Case GetType(TxDataSource).Name
DirectCast(dataSource, TxDataSource).Context = txContext

End Select

' TransactionInterceptor
Dim handler As LocalRequiredTxHandler = New LocalRequiredTxHandler()
handler.Context = txContext
_transactionInterceptor = New BTransactionInterceptor(handler)
DirectCast(_transactionInterceptor,
BTransactionInterceptor).TransactionStateHandler = txContext

End Sub

Public Class TransactionContextCreator

Private Shared _transactionContext As TransactionContext = Nothing

Public Shared Function GetTransactionContext(ByVal dataSource As
IDataSource) As ITransactionContext

If _transactionContext Is Nothing Then

_transactionContext = New TransactionContext()
_transactionContext.DataSouce = dataSource
_transactionContext.IsolationLevel = IsolationLevel.ReadCommitted

End If
Return _transactionContext

End Function

End Class

End Class
/** Bここまで **/

>> (ログに"トランザクションを開始しました"、"トランザクションをコミット
>>しました"というログが一回のトランザクションで二つずつ出ているようなの
>>ですが、こちらのテスト環境では一つずつしか出力されなかったため、そちら
>>の方も気になりました)

こちらに関しては私も気にはなっていたのですが、原因が究明できておりません。
先ほど申し上げたTransactionContextの生成や保持の仕方が影響している可能性
もあるのでしょうか?

>>・S2Container.NET 1.3.18を使った場合でも問題は再現するでしょうか?
>>(1.4.0-RC2との機能的な違いはないので関係ないと思われますが、
>>1.4.0-RC2は.NET Framework4.0上での使用を想定して作成しています。
>>.NET Framework3.5上でお使いなのであれば1.3.18の方が安定しているかと思
>>います)

開発初期ではS2Container.Net 1.3.18(S2Dao.Net 1.3.18)を使用していたのです
が、StoredProcedureの引数に配列を渡すことができず、1.4.0-RC2を.Net
Framework3.5用にビルドして使用しております。
(イレギュラーな使用方法であるとは認識しております。申し訳ありません。)

>>・自動コミットの設定はどのようになっているでしょうか?
>>(既定値を使用している場合、既定値はONかOFFか)

データプロバイダはODP.NETを使用しており、既定値はONとなっております。
こちらの設定に関しては既定の設定のままで、トランザクション属性が設定され
ている登録処理に関してはQuillで自動コミットをオフにしてトランザクション
制御を行うという認識です。
認識に何か誤りはございますでしょうか?

>>あまりお力になれず、申し訳ないです。

とんでもございません。こちらも100%の再現性がなく、発生条件も
把握できていない状況でこのような質問をしてしまい
心苦しく思っております、その中でお力添えをいただいていることに
大変感謝しております。ありがとうございます。

以上、よろしくお願いいたします。


On Wed, 11 Apr 2012 23:35:33 +0900
"kotani.k" <[E-MAIL ADDRESS DELETED]> wrote:

> 大森さん
>
> 小谷です。
>
> トランザクション開始~コミットの流れは問題なさそうですね。
> 他に気になる点としましては・・・
>
> ・VMが3機あってそれぞれがDBサーバとのことですが、
>  1回の処理でA,B,CそれぞれのDBを更新しているでしょうか?
>  (ログを拝読する限りではデータソース「001」しか使われていないようですが念のため)
>  (複数のデータソースを使用している場合、トランザクションはデータソースごとに
>  別々に発行されます。そのこととマテリアライズドビューによる同期が
>  何か問題を起こしている可能性を想定しています)
>
> ・各DB用のTransactionSettingで行っている拡張は「TypicalTransactionSetting」を 
> 
>  DataSourceNameプロパティだけoverride、のような形でしょうか?
>  それともSetupTransactionメソッドなど他のメソッドも拡張されているでしょうか?
> (ログに"トランザクションを開始しました"、"トランザクションをコミットしました"というログが
>  一回のトランザクションで二つずつ出ているようなのですが、
>  こちらのテスト環境では一つずつしか出力されなかったため、そちらの方も気になりました)
>
>
> また、こちらも更に更に念のための確認になるのでお時間があれば、の話になるのですが、
>
> ・S2Container.NET 1.3.18を使った場合でも問題は再現するでしょうか?
> (1.4.0-RC2との機能的な違いはないので関係ないと思われますが、
>  1.4.0-RC2は.NET Framework4.0上での使用を想定して作成しています。
>  .NET Framework3.5上でお使いなのであれば1.3.18の方が安定しているかと思います)
>
> ・自動コミットの設定はどのようになっているでしょうか?
>  (既定値を使用している場合、既定値はONかOFFか)
>
> あまりお力になれず、申し訳ないです。
> 以上、よろしくお願いします。
>
> 2012年4月9日15:44 K.Ohmori <[E-MAIL ADDRESS DELETED]>:
> > 小谷さん
> >
> > 大森です。レスポンスいただきありがとうございました。
> > その後、確認と検証を行いました。
> >
> >
> >> ・即時エラーを返すNO WAITではなく通常のSELECT ~ FOR UPDATE、またはWAIT 
> >> 秒数を指定してみる
> >
> > ⇒通常のFOR UPDATEは顧客からの要件として採択できないのですが
> >   WAIT秒数指定は同じ結果だろうという推定で済ませてましたので
> >   テスト登録を繰り返し実行してみましたが現象をおこせませんでした。
> >   あわせてNO WAITでもテスト登録を繰り返し実行してみましたが現象をおこせていません。
> >
> >
> >> ・SELECT~FOR UPDATE NO WAITが本当にロックをかけたい行のみ該当する条件になっているか確認する
> >> ・ストアドプロシージャ内にロックが解放されない分岐がないか見直す
> >
> > ⇒こちらについては今一度再確認しましたが、見落としはありませんでした。
> >   大まかな実装の流れはVBにてトランザクション開始 ⇒ 対象データロック ⇒ 
> > トラン追加 ⇒
> >   ストアド呼出 ⇒ ストアド実行結果に応じてコミット or ロールバック、としています。
> >
> >> ・commit/rollbackのタイミングを見直す
> >
> > ⇒こちらについてはAOPで制御しています。AOPを使用しないで制御する、といった認識でよろしいでしょうか。
> >
> > 他に考えられる検証・見直しポイントはなにかありますでしょうかね・・
> >
> >
> > 以上です。
> >
> >
> >
> >> 大森さん
> >>
> >> 小谷です。
> >>
> >> 私もGMailですが前の投稿も今回の投稿も正常に閲覧できております。
> >>
> >> >○画面を閉じずに登録を繰り返している時に発生している模様
> >> >○1回目の更新実行時にはまず発生しない
> >> > ⇒現象発生時に画面を閉じて(DB切断している)、起動し直して
> >> >  登録を実行すると正常更新できる
> >>
> >> とのことですので前の更新でかけられていたロックが解放されないうちに
> >> SELECT ~ FOR UPDATE NO WAITで次のロックをかけようとしてしまい
> >> 発生しているように思えます。
> >>
> >> ・即時エラーを返すNO WAITではなく通常のSELECT ~ FOR UPDATE、またはWAIT 
> >> 秒数を指定してみる
> >> ・SELECT~FOR UPDATE NO WAITが本当にロックをかけたい行のみ該当する条件になっているか確認する
> >> ・ストアドプロシージャ内にロックが解放されない分岐がないか見直す
> >> ・commit/rollbackのタイミングを見直す
> >>
> >> などを試した場合どうなるでしょうか?
> >> (既に確認済の事柄でしたらごめんなさい)
> >>
> >> 以上です。
> >>
> >> 2012年4月3日21:10 kubo <[E-MAIL ADDRESS DELETED]>:
> >> jfluteです。
> >>
> >>> 当方が昨日投稿しました記事を保存書庫スレッドにて拝見したところ
> >>> タイトルのみ正常で本文がすべて文字化けをおこしておりました。
> >>> MLメンバーの皆さまには大変ご迷惑をおかけしました。
> >>
> >>
> >> 一応、報告まで。
> >> 自分、GMailですが以前の投稿も正常に閲覧できていました。
> >>
> >> 2012/4/3 K.Ohmori <[E-MAIL ADDRESS DELETED]>:
> >>>
> >>> 大森と申します。
> >>>
> >>> 当方が昨日投稿しました記事を保存書庫スレッドにて拝見したところ
> >>> タイトルのみ正常で本文がすべて文字化けをおこしておりました。
> >>> MLメンバーの皆さまには大変ご迷惑をおかけしました。
> >>>
> >>> 当方にて利用しているメーラーでの投稿ですと、文字コードの問題が
> >>> あるようですので、再三で申し訳ありませんが投稿記事を
> >>> 別のメーラーから再送させていただきます。
> >>>
> >>>
> >>>
> >>> 現在従事しているプロジェクトで稼働中のシステムの
> >>> 更新処理(Quillでのトランザクション処理)にて下記の現象が発生していまして、 
> >>> 
> >>> なかなか収束できず苦しんでおります。
> >>>
> >>> どこがまずいのか指摘点があれば教えていただけないでしょうか。
> >>> もしくは同様あるいは類似した現象の解決事例をお持ちの方が
> >>> いらっしゃいましたら、どうかご教授ください。
> >>>
> >>>
> >>> [事象]
> >>> ○VB.netの画面からの更新処理を実行する際の
> >>>  トランザクション処理部にて、対象データのロックを
> >>>  行っているが、ロックに失敗して
> >>>  「ORA-01002:フェッチ順序が無効です。」が発生する
> >>> ○一貫した再現性がなく、稀にしか発生しない
> >>> ○画面を閉じずに登録を繰り返している時に発生している模様
> >>> ○1回目の更新実行時にはまず発生しない
> >>>  ⇒現象発生時に画面を閉じて(DB切断している)、起動し直して
> >>>  登録を実行すると正常更新できる
> >>> ○1度発生すると、入力内容を保持して更新処理を再実行しても
> >>>  再度失敗することがある。失敗を繰り返す時は10分以上続くこともある。
> >>>
> >>>
> >>> [システム環境]
> >>> ○サーバーOS:Windows2008 R2 (64Bit)
> >>>  ⇒VM Ware ESX Server上で稼動する仮想OSです
> >>>  ⇒VMは3つあり、サーバAに共用DBを上位に位置させ、
> >>>  その下位にサーバBとC(事業所別のDB)が同位で位置します。
> >>> ○DB:Oracle 11g R2 11.2.0.1.0(64Bit)
> >>>  ⇒VM3機A、B、CそれぞれがDBサーバであり、サーバ間の連携は
> >>>  マスタ:マテリアライズドビューでDB同期
> >>>  トラン:テキスト連携(SQL loaderで取込)
> >>> ○クライアントOS:Windows 7
> >>>  ⇒F社のデスクトップ機です
> >>>  ⇒サーバA、B、Cの物理筐体がある拠点と、クライアントの拠点は
> >>>  NTTのVPNワイドにてWAN接続されています
> >>> ○開発言語:VB.NET (Framework 3.5)
> >>> ○開発環境:Visual Studio 2008
> >>> ○S2Container.net:1.4.0 RC2
> >>> ○ODP.NET サーバー側64bit 11.2.0.0、クライアント側32bit 11.2.0.2
> >>>
> >>>
> >>> [補足]
> >>> ○トランザクション処理での更新対象テーブルが複数ある
> >>> ○トランザクション処理の冒頭、UPDATEやINSERT発行前にロックしている
> >>> ○ロックはSELECT ~ FOR UPDATE NO WAITで発行
> >>> ○トランザクション処理を実装しているサービス実装クラスのメソッドには「<Transaction()> 
> >>> 
> >>>
> >>> _」を指定
> >>> ⇒VMのDBが分かれていますので各DB用にTransactionSetting拡張しています。
> >>> ○サービス実装クラスのメソッドには「Public Overridable Function」を指定 
> >>> 
> >>> ○トランザクション処理を実装しているメソッド内で、DAOに定義した
> >>>  メソッド(※)を呼び出している
> >>>  ※「<Procedure("hogehoge")> _」を指定しPL/SQLパッケージ(ストアード・
> >>>    プロシージャ)をコールしている
> >>> ○PL/SQL内はトランザクション処理は宣言していない
> >>> ○CURSOR検索中にコミットは行っていません
> >>> ○接続プール関連の指定はすべて未指定=既定値。
> >>>  (Connection PoolやMAX Pool Size、LifeTimeなど)
> >>> ○登録実行時のメソッドの流れは下記の通り
> >>>  1)formのF10キーに割当した登録ボタンを押下
> >>>  2)formのボタンClickイベントプロシージャ呼出
> >>>  3)2)内で更新処理(formメソッド)を呼出
> >>>  4)サービスインタフェースの更新処理(「<Implementation()> _」指定)のメソッド呼出
> >>>    ⇒実体はサービス実装クラスの更新処理(「<Transaction()> _」指定)のメソッド 
> >>> 
> >>>
> >>>
> >>>  5)4)のメソッド内の冒頭で、更新処理前にロックしている
> >>>  6)トラン1~3の更新
> >>>  7)トラン4の更新
> >>>  8)5)でロックしているトラン5の更新
> >>> ○アプリケーションログを添付します
> >>> [正常系]hoge_seijou.log
> >>>  1)3行目:トランザクション処理開始
> >>>  2)6~17行目:更新対象データをロック
> >>>  3)18~24行目:トラン1をINSERT
> >>>  4)25~31行目:トラン2をINSERT
> >>>  5)32~39行目:トラン3をINSERT
> >>>  6)40~56行目:データ抽出
> >>>  7)58行目:PL/SQL呼出(トラン4を更新⇒トリガ連動⇒別テーブルデータを更新) 
> >>> 
> >>>  8)78行目:PL/SQL呼出(トラン5を更新)
> >>>  9)79・80行目:更新(コミット)正常完了
> >>> [異常系]hoge_ijou.log
> >>>  1)3行目:トランザクション処理開始
> >>>  2)6~17行目:更新対象データをロック
> >>>  3)20行目:「ORA-01002: フェッチ順序が無効です」が発生
> >>>
> >>> 以上よろしくお願いいたします。
> >
> >
> >
> > _______________________________________________
> > seasar-dotnet mailing list
> > [E-MAIL ADDRESS DELETED]
> > https://ml.seasar.org/mailman/listinfo/seasar-dotnet
> _______________________________________________
> seasar-dotnet mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet




seasar-dotnet メーリングリストの案内