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

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

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

Re[1]: テーブルデータ取得時の排他制御


(過去ログ 107 を表示中)

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

■63640 / inTopicNo.1)  テーブルデータ取得時の排他制御
  
□投稿者/ NorthIsland (1回)-(2012/09/19(Wed) 17:22:30)

分類:[.NET 全般] 

2012/09/19(Wed) 18:01:56 編集(投稿者)

開発環境:VB2005 SQLServer

お世話になります。
現在,データ登録/更新処理の改修を行っています。
更新の際に、採番テーブルより取得した値を登録対象テーブルに格納しています。
また、採番テーブルよりデータ取得後は、UPDATE文により+1カウントアップを行っています。

下記が処理ロジックの抜粋となりますが、同時に更新処理を行われた際に採番テーブルより
取得した番号が同じになるという現象が発生してしまいます。
行ロックなどの手法を試みましたが、どうしてもうまくいきません。

FOR UPDATE文は下記のロジック内では使用できないので、 WITH(ROWLOCK, UPDLOCK)
などを試しています。
トランザクション処理も考えないといけないので、ストアドファンクション化する方法も考えています。
ストアド化、別の方法など重複防止の為のアドバイスをお願いします。
よろしくお願いいたします。

下記が採番テーブル取得後、採番テーブル更新までの処理ロジックの抜粋です。
※取得採番データは、登録対象データとして使用します。
※EB.qt(TestCd),Shubetu,EB.qt(GrpCd),Nendoなどは引数です。

'採番テーブル取得
strSQL = "SELECT NEW_NO, END_NO FROM TB_SAIBAN "
strSQL += " WHERE SAIBAN_CD = " & EB.qt(TestCd)
strSQL += " AND SAIBAN_SHUBETU = " & Shubetu
strSQL += " AND SAIBAN_GRP_CD = " & EB.qt(GrpCd)
strSQL += " AND SAIBAN_NENDO = " & Nendo
'SQL実行
rStr = DSQL.DoSQL(strSQL)

If rStr IsNot Nothing Then
Return rStr
End If

If DSQL.rDSet.Tables(0).Rows.Count > 0 Then
cNewNo = DSQL.rDSet.Tables(0).Rows(0).Item("NEW_NO")
cEndNo = DSQL.rDSet.Tables(0).Rows(0).Item("END_NO")
If cNewNo = cEndNo Then
rRet = 9
Else
'採番テーブル更新
strSQL = "UPDATE TB_SAIBAN "
strSQL += " SET NEW_NO = " & cNewNo + 1
strSQL += " WHERE SAIBAN_CD = " & EB.qt(TestCd)
strSQL += " AND SAIBAN_SHUBETU = " & Shubetu
strSQL += " AND SAIBAN_GRP_CD = " & EB.qt(GrpCd)
strSQL += " AND SAIBAN_NENDO = " & Nendo
'SQL実行
rStr = DSQL.DoSQL(strSQL)

If rStr IsNot Nothing Then
Return rStr
End If

rNewNo = cNewNo
rRet = 1
End If

Else
'採番テーブルにデータ無の場合
End If
</pre></pre>
引用返信 編集キー/
■63641 / inTopicNo.2)  Re[1]: テーブルデータ取得時の排他制御
□投稿者/ かたぎり (3回)-(2012/09/19(Wed) 23:45:54)
トランザクションスコープ使えば可能な感じがします。

transactionScope で検索してみてください。

マルチスレッドでの更新が考えられる場合には、
interlocked を使ってメソッド処理自身を単一直列化する方法もあるかと思います。

メソッド単体の話というより、そのメソッドの使い方、呼び出し方の情報がもうすこしあると良いかもですね。


No63640 (NorthIsland さん) に返信
> 2012/09/19(Wed) 18:01:56 編集(投稿者)
>
> 開発環境:VB2005 SQLServer
>
> お世話になります。
> 現在,データ登録/更新処理の改修を行っています。
> 更新の際に、採番テーブルより取得した値を登録対象テーブルに格納しています。
> また、採番テーブルよりデータ取得後は、UPDATE文により+1カウントアップを行っています。
>
> 下記が処理ロジックの抜粋となりますが、同時に更新処理を行われた際に採番テーブルより
> 取得した番号が同じになるという現象が発生してしまいます。
> 行ロックなどの手法を試みましたが、どうしてもうまくいきません。
>
> FOR UPDATE文は下記のロジック内では使用できないので、 WITH(ROWLOCK, UPDLOCK)
> などを試しています。
> トランザクション処理も考えないといけないので、ストアドファンクション化する方法も考えています。
> ストアド化、別の方法など重複防止の為のアドバイスをお願いします。
> よろしくお願いいたします。
>
> 下記が採番テーブル取得後、採番テーブル更新までの処理ロジックの抜粋です。
> ※取得採番データは、登録対象データとして使用します。
> ※EB.qt(TestCd),Shubetu,EB.qt(GrpCd),Nendoなどは引数です。
>
> '採番テーブル取得
> strSQL = "SELECT NEW_NO, END_NO FROM TB_SAIBAN "
> strSQL += " WHERE SAIBAN_CD = " & EB.qt(TestCd)
> strSQL += " AND SAIBAN_SHUBETU = " & Shubetu
> strSQL += " AND SAIBAN_GRP_CD = " & EB.qt(GrpCd)
> strSQL += " AND SAIBAN_NENDO = " & Nendo
> 'SQL実行
> rStr = DSQL.DoSQL(strSQL)
>
> If rStr IsNot Nothing Then
> Return rStr
> End If
>
> If DSQL.rDSet.Tables(0).Rows.Count > 0 Then
> cNewNo = DSQL.rDSet.Tables(0).Rows(0).Item("NEW_NO")
> cEndNo = DSQL.rDSet.Tables(0).Rows(0).Item("END_NO")
> If cNewNo = cEndNo Then
> rRet = 9
> Else
> '採番テーブル更新
> strSQL = "UPDATE TB_SAIBAN "
> strSQL += " SET NEW_NO = " & cNewNo + 1
> strSQL += " WHERE SAIBAN_CD = " & EB.qt(TestCd)
> strSQL += " AND SAIBAN_SHUBETU = " & Shubetu
> strSQL += " AND SAIBAN_GRP_CD = " & EB.qt(GrpCd)
> strSQL += " AND SAIBAN_NENDO = " & Nendo
> 'SQL実行
> rStr = DSQL.DoSQL(strSQL)
>
> If rStr IsNot Nothing Then
> Return rStr
> End If
>
> rNewNo = cNewNo
> rRet = 1
> End If
>
> Else
> '採番テーブルにデータ無の場合
> End If
> </pre></pre>
引用返信 編集キー/
■63642 / inTopicNo.3)  Re[1]: テーブルデータ取得時の排他制御
□投稿者/ shu (74回)-(2012/09/20(Thu) 08:09:43)
No63640 (NorthIsland さん) に返信

(1)トランザクション開始

(2)WITH (TABLOCKX, HOLDLOCK)で採番テーブルSelect
※TABLOCKXはROWLOCKでも大丈夫かもしれないです。

(3)データ更新処理

(4)コミットまたはロールバック

とすればトランザクション中はロックされるので
他の処理は待たされることになり重複はさけられます。
採番テーブルのロックで待ちになるので多分大丈夫だとは思いますが
デッドロックにならないよう気をつけましょう。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -