none
ストアドのトランザクションについて RRS feed

  • 質問

  • VB2010express、Sqlserver2012で開発を行っています。

    VBで作成したプログラム内からストアドプロシージャを呼び出して

    DBへログデータの追加を行っています。

    ストアド内でトランザクションをBEGIN~COMMITしているのですが

    ストアドを呼び出すプログラムの方でエラーが発生し、トランザクションをロールバックすると

    ストアドで追加したログデータもロールバックしてしまいます。

    以前はORACLEベースで作られていたシステムで、いわゆる自律型トランザクションと同等のことを

    行いたいのですが、Sqlserverではどのようにすればよいのでしょうか?

    まったく同じことは出来ないとしても、とりあえずストアド側のログ追加はストアドでコミットしたいと思ってます。

    そのようなやり方がありましたら、併せてご教授願います。


    2015年2月14日 6:07

回答

  • ストアドの処理内容がよくわかりませんが、ログデータの追加しているだけであればそもそもロールバックしないのが正しいように思われますが・・・。

    その他の処理があるようであれば、先ずログデータの追加を行い、セーブポイントを設定し、その他の処理を行い、その結果次第でセーブポイントにロールバックを行い、コミットする、という方法があります。
    https://technet.microsoft.com/ja-jp/library/ms378414%28v=sql.110%29.aspx

    あるいは、ログデータの追加とその他の処理のトランザクションを分けてしまい、ログデータの追加がコミットできたらその他の処理を行う、という形でも同等の結果になるかと思います。


    MCITP(Database Developer/Database Administrator)

    • 回答としてマーク Dreizehn 2015年2月17日 12:04
    2015年2月17日 2:56
  • ・・・SQL Serverの単一のストアド内では、この様な処理は出来なかったと記憶しているのですが記憶違いでしょうか。

    ログ登録が先頭に持ってこれるのであればセーブポイントは有りだと思いますが、
    個人的にはSQL-CLRが出来る範囲は広いと思います。
    ※内部で別のConnectionを生成してログ出力-Commitを行う。

    ただし、T-SQLをSQL-CLRに変更するのはほぼ作り直しになります。

    • 回答としてマーク Dreizehn 2015年2月17日 12:03
    2015年2月17日 9:34
  • トランザクションのネストの問題だと思いました。例えば、以下の記事が参考になると思います。

    SQL Server 2000でのコネクション/トランザクション問題
    http://d.hatena.ne.jp/PoohKid/20060608/p2

    また、トランザクションションに参加せずに処理を開始することもできますので、ログの記録などに利用することができます。

    (参考)
    トランザクション スコープを使用した暗黙的なトランザクションの実装
    https://msdn.microsoft.com/ja-jp/library/ms172152(v=vs.90).aspx

    上記より抜粋

    --- 抜粋開始 -----------------------------------

    Suppress は、コード セクションで実行された操作を保持したり、操作が失敗した場合でもアンビエント トランザクションを中止しない場合に役立ちます。たとえば、ログの記録や監査操作を実行する場合や、アンビエント トランザクションがコミットしても中止してもサブスクライバにイベントを公開する場合などです。

    --- 抜粋終了 -----------------------------------


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク Dreizehn 2015年2月19日 4:46
    2015年2月18日 3:11

すべての返信

  • ストアドの処理内容がよくわかりませんが、ログデータの追加しているだけであればそもそもロールバックしないのが正しいように思われますが・・・。

    その他の処理があるようであれば、先ずログデータの追加を行い、セーブポイントを設定し、その他の処理を行い、その結果次第でセーブポイントにロールバックを行い、コミットする、という方法があります。
    https://technet.microsoft.com/ja-jp/library/ms378414%28v=sql.110%29.aspx

    あるいは、ログデータの追加とその他の処理のトランザクションを分けてしまい、ログデータの追加がコミットできたらその他の処理を行う、という形でも同等の結果になるかと思います。


    MCITP(Database Developer/Database Administrator)

    • 回答としてマーク Dreizehn 2015年2月17日 12:04
    2015年2月17日 2:56
  • ・・・SQL Serverの単一のストアド内では、この様な処理は出来なかったと記憶しているのですが記憶違いでしょうか。

    ログ登録が先頭に持ってこれるのであればセーブポイントは有りだと思いますが、
    個人的にはSQL-CLRが出来る範囲は広いと思います。
    ※内部で別のConnectionを生成してログ出力-Commitを行う。

    ただし、T-SQLをSQL-CLRに変更するのはほぼ作り直しになります。

    • 回答としてマーク Dreizehn 2015年2月17日 12:03
    2015年2月17日 9:34
  • 回答ありがとうございます。

    セーブポイントというのは初めて聞きました、

    やはりトランザクションを分けるのが常套なんでしょうか。

    リンク先も含め検討してみます。

    ありがとうございました。

    2015年2月17日 12:03
  • 作り直しは時間的な余裕がありませんので難しいですが

    SQL-CLRと言うものも含め色々道を探ってみます。

    回答ありがとうございました。

    2015年2月17日 12:06
  • トランザクションのネストの問題だと思いました。例えば、以下の記事が参考になると思います。

    SQL Server 2000でのコネクション/トランザクション問題
    http://d.hatena.ne.jp/PoohKid/20060608/p2

    また、トランザクションションに参加せずに処理を開始することもできますので、ログの記録などに利用することができます。

    (参考)
    トランザクション スコープを使用した暗黙的なトランザクションの実装
    https://msdn.microsoft.com/ja-jp/library/ms172152(v=vs.90).aspx

    上記より抜粋

    --- 抜粋開始 -----------------------------------

    Suppress は、コード セクションで実行された操作を保持したり、操作が失敗した場合でもアンビエント トランザクションを中止しない場合に役立ちます。たとえば、ログの記録や監査操作を実行する場合や、アンビエント トランザクションがコミットしても中止してもサブスクライバにイベントを公開する場合などです。

    --- 抜粋終了 -----------------------------------


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク Dreizehn 2015年2月19日 4:46
    2015年2月18日 3:11
  • 回答ありがとうございます。

    1番目のやり方が一番しっくり来そうですね。

    リンク先を参照して、検討してみます。

    2015年2月19日 4:48