C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[7]: トランザクション処理について


(過去ログ 14 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■4635 / inTopicNo.1)  トランザクション処理について
  
□投稿者/ Question (6回)-(2007/06/21(Thu) 12:56:27)

分類:[データベース全般] 

SQLServer2005で、以下の様な処理を行うトランザクション処理について質問させて頂きます。

 @1レコードずつデータを更新
 A正常終了した件数が【規定値】以上になった時点で一度コミット
 B最後に一括でコミット

下記のコードで動作を確認してみたのですが、「EXECUTE 後のトランザクション数は、
COMMIT TRANSACTION または ROLLBACK TRANSACTION ステートメントが
ないことを示しています。」というエラーが出ます。

どなたか問題のある箇所をご指摘頂けますでしょうか?

※【正常終了した件数】>【規定値】の判定をせず、正常終了した
 場合に無条件でコミットすると問題ないのですが・・・。




BEGIN TRANSACTION Main

 WHILE (条件式)
 BEGIN

 BEGIN TRANSACTION Sub

 【1レコードずつ更新処理】

 IF 【更新処理=正常終了】
 BEGIN
 【処理が正常終了した場合カウントアップ】

 IF 【正常終了した件数】 >【規定値】
 COMMIT TRANSACTION Sub
 END

 ELSE
 ROLLBACK TRANSACTION Sub

 END

COMMIT TRANSACTION Main



引用返信 編集キー/
■4637 / inTopicNo.2)  Re[1]: トランザクション処理について
□投稿者/ HiJun (44回)-(2007/06/21(Thu) 13:52:59)
これってストアドプロシージャかなんかです?

であれば、プロシージャをコールする実際のプログラムのほうで
トランザクション処理をつけてみてはいかがですか?
引用返信 編集キー/
■4639 / inTopicNo.3)  Re[2]: トランザクション処理について
□投稿者/ Question (7回)-(2007/06/21(Thu) 14:11:57)
No4637 (HiJun さん) に返信
> これってストアドプロシージャかなんかです?
>
> であれば、プロシージャをコールする実際のプログラムのほうで
> トランザクション処理をつけてみてはいかがですか?

→HiJun さん、早速ご回答頂きありがとうございます。
 ご提案されたように、コール側での制御も一つの手段として挙げられるのですが、
 仕様(制限?)としてトランザクション処理はストアドプロシージャ内でしなくては
 ならないので・・・。

※試しに「COMMIT TRANSACTION Sub」の前に「Print 〜」などの処理行を追加すると
 【規定値】を超えた時に「COMMIT TRANSACTION Sub」が実行されました???
引用返信 編集キー/
■4640 / inTopicNo.4)  Re[2]: トランザクション処理について
□投稿者/ iwaiwa (21回)-(2007/06/21(Thu) 14:12:11)
commitするのは、1回じゃダメなのでしょうか?
全部まとめてcommitとした方が普通だと思われますが…
引用返信 編集キー/
■4642 / inTopicNo.5)  Re[3]: トランザクション処理について
□投稿者/ Question (9回)-(2007/06/21(Thu) 14:14:55)
iwaiwaさん、回答頂きありがとうございます。

commit処理が1回のみであれば問題ないのですが、以下のような仕様なので・・・。

「commit条件」:@正常に更新処理が行われたレコード数が規定値を超えた場合に
         一度commit処理をする。
        A全体の処理が完了した時点で一括でcommitする。

引用返信 編集キー/
■4643 / inTopicNo.6)  Re[4]: トランザクション処理について
□投稿者/ 片桐 (24回)-(2007/06/21(Thu) 14:34:55)
サンプルソースで気になったのですが、
BEGIN TRANSACTION とコミットorロールバックの回数があわないような……

BEGINとCOMMIT、BEGINとROLLBACK、は必ずペアになるようにしないといけませんので

ループ開始直前にBEGIN
規定回数でCOMMIT→BEGIN、ROLLBACK→BEGIN
ループ終了直後にCOMMITorROLLBACK

なら組み合わせが合うので大丈夫だとおもうのですけれど。

引用返信 編集キー/
■4645 / inTopicNo.7)  Re[5]: トランザクション処理について
□投稿者/ Question (11回)-(2007/06/21(Thu) 14:46:56)
No4643 (片桐 さん) に返信
> サンプルソースで気になったのですが、
> BEGIN TRANSACTION とコミットorロールバックの回数があわないような……
>
> BEGINとCOMMIT、BEGINとROLLBACK、は必ずペアになるようにしないといけませんので
>
> ループ開始直前にBEGIN
> 規定回数でCOMMIT→BEGIN、ROLLBACK→BEGIN
> ループ終了直後にCOMMITorROLLBACK
>
> なら組み合わせが合うので大丈夫だとおもうのですけれど。
>
 →片桐さん、ご回答頂きありがとうございます。
  ご指摘頂いた箇所についてですが、BEGIN TRANSACTION 〜 COMMIT or ROLLBACKは以下の
  ペアになっています。

  =================================
  BEGIN TRANSACTION MAIN

   <ループ開始>

    BEGIN TRANSACTION

    ・規定値を超えたら
     COMMIT SUB

    ・更新処理がエラーだった時点で
     ROLLBACK SUB

   <ループ終了>

  COMMIT TRANSACTION MAIN
  =================================

  ROLLBACK MAINも必要ということでしょうか???
引用返信 編集キー/
■4646 / inTopicNo.8)  Re[6]: トランザクション処理について
□投稿者/ HiJun (45回)-(2007/06/21(Thu) 15:00:19)
であれば、
指定ループ件数のところでCommitするかと思いますが
その後すぐにトランザクション開始処理をつければOKではないかと
思います。


引用返信 編集キー/
■4650 / inTopicNo.9)  Re[7]: トランザクション処理について
□投稿者/ 囚人 (109回)-(2007/06/21(Thu) 15:37:28)
BEGIN END を省いている箇所があるから見にくいんですけど、整形すると以下でしょうか?
「更新処理が正常終了で、正常終了した件数が既定値以下の場合」は、Transaction Sub がコミットもロールバックもされていませんが。

BEGIN TRANSACTION Main

 WHILE (条件式)
 BEGIN

	 BEGIN TRANSACTION Sub

	 【1レコードずつ更新処理】

	 IF 【更新処理=正常終了】
	 BEGIN
		 【処理が正常終了した場合カウントアップ】

		 IF 【正常終了した件数】 >【規定値】
			 COMMIT TRANSACTION Sub
	 END

	 ELSE
		 ROLLBACK TRANSACTION Sub

 END

COMMIT TRANSACTION Main

引用返信 編集キー/
■4651 / inTopicNo.10)  Re[6]: トランザクション処理について
□投稿者/ J.J. (1回)-(2007/06/21(Thu) 15:40:18)
No4645 (Question さん) に返信
>   =================================
>   BEGIN TRANSACTION MAIN
>
>    <ループ開始>
>
>     BEGIN TRANSACTION
>
>     ・規定値を超えたら
>      COMMIT SUB
>
>     ・更新処理がエラーだった時点で
>      ROLLBACK SUB
>
>    <ループ終了>
>
>   COMMIT TRANSACTION MAIN
>   =================================
はじめまして。
これだとCOMMIT or ROLLBACKが呼ばれる前に何度もBEGIN TRANSACTIONが実行されてませんか?

引用返信 編集キー/
■4653 / inTopicNo.11)  Re[7]: トランザクション処理について
□投稿者/ 中博俊 (1102回)-(2007/06/21(Thu) 15:42:46)
中博俊 さんの Web サイト
仕様がこうだからとか言わずになぜそうしているかを考えましょうね。
要はコミット件数が大きすぎて一括コミットできない場合の分割トランザクションという典型例です。

コミットはIFの中に埋め込むことはできませんので、決定論的に存在させる必要があると思います。
やり方ですが、下記のような流れにしてください

declare @対象 table ( ....省略)
insert into @省略 select top 100 from 対象データ
while (1)
begin tran
対象データ分回す
commit tran
上のinsertとおなじ
if(select count(L) from @対象=0)
begin
return
end
end

引用返信 編集キー/
■4654 / inTopicNo.12)  Re[7]: トランザクション処理について
□投稿者/ Question (13回)-(2007/06/21(Thu) 15:45:29)
No4646 (HiJun さん) に返信
> であれば、
> 指定ループ件数のところでCommitするかと思いますが
> その後すぐにトランザクション開始処理をつければOKではないかと
> 思います。
>
>
 →commitではなくsavepointを使用したパターンで検証していたところ
  正常に完了しました。

  =================================
  BEGIN TRANSACTION

   <ループ開始>
    BEGIN TRANSACTION
    ・規定値を超えたら「SAVEPOINT」作成
    ・更新処理がエラーだった時点で「ROLLBACK」&「Return」
   <ループ終了>

  COMMIT TRANSACTION
  =================================

色々とアドバイスをして頂きありがとうございました。 m(__)m
引用返信 編集キー/
■4656 / inTopicNo.13)  Re[7]: トランザクション処理について
□投稿者/ 囚人 (110回)-(2007/06/21(Thu) 16:01:20)
2007/06/21(Thu) 16:02:41 編集(投稿者)

削除
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -