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

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

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

DB 複数テーブルへの同時書き込みが失敗するケースについて

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

■97003 / inTopicNo.1)  DB 複数テーブルへの同時書き込みが失敗するケースについて
  
□投稿者/ az (19回)-(2021/03/15(Mon) 09:06:21)

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

SQL Server 2016を使用し、複数のパソコンから1つのデータベースへデータ書き込みを行うシステムを開発しています。

アプリケーションの開発環境は Visual Studio Express 2017 for Windows Desktop
言語はC#、.NET Framework 4.7.2を使用して Windowsフォームアプリケーションを開発しています。

アプリケーションからの1回の書き込み時、複数テーブルにデータを書きこみます。(INSERTでレコード追加 または UPDATEで既存のレコード更新)
不整合を防ぐことを目的とし、トランザクション機構を入れたいのですが
「テーブルAには書きこめたが、他のテーブルには書き込み失敗した」というケースは具体的にどのようなものが考えられるでしょうか?
なお、データベースはサーバに1つだけ作成し、その中に複数テーブルを作成しています。(データベースをまたがった書き込みは行わない)


当方で考えるのは、以下のケースです。
他にもありましたら教えていただけないでしょうか?

データベースを配置しているサーバのディスク破損
データベース書き込みエラー(型が異なる、サイズが異なるなど。 アプリケーション側でもバリデーションチェックはするが、それでも書き込みエラーとなる可能性を考慮して、保険)
引用返信 編集キー/
■97004 / inTopicNo.2)  Re[1]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ furu (105回)-(2021/03/15(Mon) 09:40:42)
No97003 (az さん) に返信
> 他にもありましたら教えていただけないでしょうか?
いろいろありますね。
・通信障害・停電
・ディスク容量オーバー
・制約チェックエラー
  primary key
  foreign key
  unique
   ※どんなにアプリケーション側でチェックしても
    書き込んだ瞬間に正常かどうかはわからない
引用返信 編集キー/
■97005 / inTopicNo.3)  Re[1]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ WebSurfer (2200回)-(2021/03/15(Mon) 10:36:59)
No97003 (az さん) に返信
> SQL Server 2016を使用し、複数のパソコンから1つのデータベースへデータ書き込みを行うシステムを開発しています。

同時実行制御が問題のような気がしますが(むしろトランザクションより)、それは考えないという前提ですか?
引用返信 編集キー/
■97006 / inTopicNo.4)  Re[2]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ ぶなっぷ (266回)-(2021/03/15(Mon) 10:56:57)
何を懸念しているかにより回答が変わる気がしますが、
ハードウェア問題による書き込み失敗は回避不能なことがほとんどなので、ソフトウェア
に起因するものに限定するならば、以下のようなものでしょうか。

・テーブルが削除済みだった
・テーブルの定義が変わっていた(フィールド名/データ型/...)
・範囲外の値を書き込もうとした
・キー制約違反(重複キー書き込みなど)
・デッドロック

引用返信 編集キー/
■97007 / inTopicNo.5)  Re[1]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ ニケ (15回)-(2021/03/15(Mon) 11:42:06)
No97003 (az さん) に返信
トランザクション機構を入れても不整合は起こりますよね。

例えば、データ参照時にSelectした値を元にUpdateした場合、
A端末から参照
B端末から参照
A端末から更新
B端末から更新
で不整合が起こります。あくまで更新処理1セットの内部で
の不整合を防ぐのがトランザクションですよね。

WebSurfer さんの指摘もここだと思うのですが、
トランザクション外でロジック的に間違っていて起こる不整合
は話題にしておらず、トランザクション処理を実行した時の
処理内のエラーパターンを知りたいのでしょうか?ロジック的
にはエラートラップ一択で話は終わりそうなのですが、テスト
パターンとして事前に考えられるものをテストしたいという
事でしょうか?
事前に完璧に全てを網羅することは不可能だと思いますが、
どういった目的でどの程度の範囲で質問しているのでしょうか?
引用返信 編集キー/
■97008 / inTopicNo.6)  Re[2]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ az (21回)-(2021/03/15(Mon) 12:49:34)
回答ありがとうございます。
確かに、トランザクション外でのデータ不整合はあり得るのですが、
そもそもトランザクション機構が全く実装されていないコードにトランザクション機構を追加するにあたり
「なぜ追加するのか」(回答としては1回の書き込みにおけるデータ不整合を防ぐため)
「1回の書き込みに対するデータ不整合が発生するのは、どのようなケースなのか」を
理解できていない人に説明する目的で(今ですと当方も説明できないため)知りたいと思って質問させていただきました。



No97007 (ニケ さん) に返信
> ■No97003 (az さん) に返信
> トランザクション機構を入れても不整合は起こりますよね。
>
> 例えば、データ参照時にSelectした値を元にUpdateした場合、
> A端末から参照
> B端末から参照
> A端末から更新
> B端末から更新
> で不整合が起こります。あくまで更新処理1セットの内部で
> の不整合を防ぐのがトランザクションですよね。
>
> WebSurfer さんの指摘もここだと思うのですが、
> トランザクション外でロジック的に間違っていて起こる不整合
> は話題にしておらず、トランザクション処理を実行した時の
> 処理内のエラーパターンを知りたいのでしょうか?ロジック的
> にはエラートラップ一択で話は終わりそうなのですが、テスト
> パターンとして事前に考えられるものをテストしたいという
> 事でしょうか?
> 事前に完璧に全てを網羅することは不可能だと思いますが、
> どういった目的でどの程度の範囲で質問しているのでしょうか?
引用返信 編集キー/
■97009 / inTopicNo.7)  Re[3]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ WebSurfer (2201回)-(2021/03/15(Mon) 13:33:04)
No97008 (az さん) に返信
> 回答ありがとうございます。
> 確かに、トランザクション外でのデータ不整合はあり得るのですが、
> そもそもトランザクション機構が全く実装されていないコードにトランザクション機構を追加するにあたり


そもそもの話をするなら、そもそも Windows Forms アプリで複数のユーザーが SQL Server にアクセスするのは
セキュリティ的に大きな問題がありそうで、そこから考え直すべきではないかと思いますが、とりあえずそこは
置いといて・・・

> 「なぜ追加するのか」(回答としては1回の書き込みにおけるデータ不整合を防ぐため)
> 「1回の書き込みに対するデータ不整合が発生するのは、どのようなケースなのか」を

一回の書き込みと言っても、最初の質問に書いたあったようにその中で、

> 複数テーブルにデータを書きこみます。(INSERTでレコード追加 または UPDATEで既存のレコード更新)

ということをするのですよね。「INSERTでレコード追加」はできたとして「UPDATEで既存のレコード更新」が
何らかの問題でできないということがあると思います。

追加しただけで更新しないと不整合が出るということはあるのでは? 例えば追加したレコードを既存のレコ
ードが参照しているような場合。既存のレコードから追加したレコードを探しても見つからないということに
なるかも。

それがまずいということであれば、トランザクション処理で「INSERTでレコード追加」も「UPDATEで既存の
レコード更新」もなかったことにする必要があるのでは?

それは同時実行制御の問題とは別の話で、例えば管理者一人しか DB にアクセスしない(同時実行制御の
問題は起こらない)という場合でも、トランザクション処理は必要になると思うのですが。
引用返信 編集キー/
■97010 / inTopicNo.8)  Re[4]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ az (22回)-(2021/03/15(Mon) 14:48:42)
回答ありがとうございます。
前提条件を書いたところかえって混乱させてしまいすみません。
同時制御は一旦抜きにして(当然、同時制御にあたっての問題点も検討する必要があるのですが)
「1台のPCで、1人しかDBにアクセスしない」ケースでのトランザクション処理がなぜ必要なのか、というところが
説明すべき人に伝わっていないので、なぜ必要なのかを説明したいため、その例をご教示いただきたく思います。
引用返信 編集キー/
■97011 / inTopicNo.9)  Re[5]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ WebSurfer (2202回)-(2021/03/15(Mon) 15:30:10)
No97010 (az さん) に返信

> 「1台のPCで、1人しかDBにアクセスしない」ケースでのトランザクション処理がなぜ必要なのか、というところが
> 説明すべき人に伝わっていないので、なぜ必要なのかを説明したいため、その例をご教示いただきたく思います。

No97009 に書いたつもりですけど?

もう一回書きます。

> 「なぜ追加するのか」(回答としては1回の書き込みにおけるデータ不整合を防ぐため)
> 「1回の書き込みに対するデータ不整合が発生するのは、どのようなケースなのか」を

一回の書き込みと言っても、最初の質問に書いたあったようにその中で、

> 複数テーブルにデータを書きこみます。(INSERTでレコード追加 または UPDATEで既存のレコード更新)

ということをするのですよね。「INSERTでレコード追加」はできたとして「UPDATEで既存のレコード更新」が
何らかの問題でできないということがあると思います。

追加しただけで更新しないと不整合が出るということはあるのでは? 例えば追加したレコードを既存のレコ
ードが参照しているような場合。既存のレコードから追加したレコードを探しても見つからないということに
なるかも。

それがまずいということであれば、トランザクション処理で「INSERTでレコード追加」も「UPDATEで既存の
レコード更新」もなかったことにする必要があるのでは?
引用返信 編集キー/
■97012 / inTopicNo.10)  Re[5]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ furu (106回)-(2021/03/15(Mon) 15:31:38)
No97010 (az さん) に返信
> 「1台のPCで、1人しかDBにアクセスしない」ケースでのトランザクション処理がなぜ必要なのか、というところが
> 説明すべき人に伝わっていないので、なぜ必要なのかを説明したいため、その例をご教示いただきたく思います。
なぜ必要かなら、銀行の例がわかりやすいと思います。

Aさんの口座からBさんの口座に1万円振り替えるとします。

  1.update 残高マスタ set 残高 = 残高 - 10000 where Aさんの口座;
  2.update 残高マスタ set 残高 = 残高 + 10000 where Bさんの口座;

トランザクション処理していないで、2でエラーとなった場合
Aさんの口座の残高は1万円減っているのに
Bさんの口座の残高はそのままで、全体の合計金額が合わなくなります。

トランザクション処理している場合
ロールバックで1のupdateは取り消され、Aさんの口座の残高もそのままで
全体の合計金額は合います。
引用返信 編集キー/
■97013 / inTopicNo.11)  Re[6]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ az (23回)-(2021/03/15(Mon) 15:53:53)
ご教示ありがとうございます。

(1) Aのテーブルにデータを追加する
(2) Bのテーブルにはデータを更新する 

1回の処理で(1)(2)を確実に行わなければならない(そうしないと整合性が取れない) 場合、
「(1)はできたが、(2)はできなかった」という場合は、ロールバックして(1)(2)を取り消さなければなりません。

 というところまでは理解できました。


現時点での問題は、「(2)はできなかった」のケースがどういう要因で起こりえるのかということについて把握したいと思っています。
(いろんな要因を説明していただきました方、ありがとうございます。)


また、不明点があります。例えば、通信障害・停電による失敗の場合、
これは発生後、(通信回線・電源復旧後) アプリケーション側でのロールバックは不可能でしょうか?


他にも「特定のテーブルが更新できなかった」という要因についてありましたら教えていただけないでしょうか。


引用返信 編集キー/
■97014 / inTopicNo.12)  Re[5]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ 魔界の仮面弁士 (3007回)-(2021/03/15(Mon) 16:15:02)
2021/03/15(Mon) 18:44:17 編集(投稿者)

No97010 (az さん) に返信
> 「1台のPCで、1人しかDBにアクセスしない」ケースでのトランザクション処理がなぜ必要なのか、

複数のデータ更新処理があった場合、前半の処理は成功したものの
後半の処理が何らかのエラーによって阻害されてしまうケースとして、たとえば:

 表領域不足(例:空き領域は存在していたが、エクステントを確保できなかった)
 桁あふれ(例:数値10桁な金額欄に売上額をセットする処理において、全店合計額が100億円を超えていた)
 ネットワークの切断(例:無線LANの電波不調、有線LANのケーブル抜け、輻輳など)…スタンドアロン環境の場合は考慮不要
 予期していなかったプログラムの不具合(例:自動採番される ID の枯渇、データチェック漏れによる型変換エラーなど)
 アプリケーションの強制終了(例:メモリ不足、予定外の Windows Update による再起動など)


その他、SQL Server に当てはまる事象では無いのですが、
データベースによっては製品特性上の理由によって、
トランザクション処理が実質的に必須となりうるケースがあります。
http://www.canalian.com/workshop/access/JetCache.html


SQL Server の場合は、IMPLICIT_TRANSACTIONS をどう設定すべきかも
開発段階で決めておいた方が良いですね。
引用返信 編集キー/
■97016 / inTopicNo.13)  Re[6]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ az (24回)-(2021/03/16(Tue) 14:24:02)
回答ありがとうございます。
「アプリケーション側でデータのチェック(バリデーションチェック)ができているのであれば、トランザクション処理を追加する必要があるのか?」という質問に対し
うまく答えることができなかったため、具体例を知ることができて勉強になりました。
(まだ、100%理解できているわけではないのですが、DBの領域不足等の要因などの具体例がわかりました。)



No97014 (魔界の仮面弁士 さん) に返信
> 2021/03/15(Mon) 18:44:17 編集(投稿者)
>
> ■No97010 (az さん) に返信
>>「1台のPCで、1人しかDBにアクセスしない」ケースでのトランザクション処理がなぜ必要なのか、
>
> 複数のデータ更新処理があった場合、前半の処理は成功したものの
> 後半の処理が何らかのエラーによって阻害されてしまうケースとして、たとえば:
>
>  表領域不足(例:空き領域は存在していたが、エクステントを確保できなかった)
>  桁あふれ(例:数値10桁な金額欄に売上額をセットする処理において、全店合計額が100億円を超えていた)
>  ネットワークの切断(例:無線LANの電波不調、有線LANのケーブル抜け、輻輳など)…スタンドアロン環境の場合は考慮不要
>  予期していなかったプログラムの不具合(例:自動採番される ID の枯渇、データチェック漏れによる型変換エラーなど)
>  アプリケーションの強制終了(例:メモリ不足、予定外の Windows Update による再起動など)
>
>
> その他、SQL Server に当てはまる事象では無いのですが、
> データベースによっては製品特性上の理由によって、
> トランザクション処理が実質的に必須となりうるケースがあります。
> http://www.canalian.com/workshop/access/JetCache.html
>
>
> SQL Server の場合は、IMPLICIT_TRANSACTIONS をどう設定すべきかも
> 開発段階で決めておいた方が良いですね。
引用返信 編集キー/
■97018 / inTopicNo.14)  Re[7]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ ニケ (16回)-(2021/03/16(Tue) 16:20:44)
No97013 (az さん) に返信
> また、不明点があります。例えば、通信障害・停電による失敗の場合、
> これは発生後、(通信回線・電源復旧後) アプリケーション側でのロールバックは不可能でしょうか?
アプリケーション側では不可能なはず。
同じトランザクションを再開するような仕組みが無いはず。

『トランザクション処理中の接続断』に対するデータベース側の対応が実行されると思います。
この時、『暗黙的コミット』が行われるかロールバックされるかはDBMS製品の仕様によって異なります。
設定によって変更できるDBMS製品もあると思います。
(魔界の仮面弁士さんが書いているIMPLICIT_TRANSACTIONS も関連事項かもしれません)
また、オブジェクトの作成、削除、定義変更を行うDDL (Data Definition Language) 文 を実行した場合、
『暗黙的コミット』されるなどの例外的な動作もあります。結局、掲示板等での説明を鵜呑みにせず、
実際にテストして確認して下さい。
引用返信 編集キー/
■97019 / inTopicNo.15)  Re[7]: DB 複数テーブルへの同時書き込みが失敗するケースについて
□投稿者/ 魔界の仮面弁士 (3008回)-(2021/03/16(Tue) 16:55:34)
No97013 (az さん) に返信
> また、不明点があります。例えば、通信障害・停電による失敗の場合、
> これは発生後、(通信回線・電源復旧後) アプリケーション側でのロールバックは不可能でしょうか?

どこで障害が発生した時の話をされていますか?


明示的にコミット済みのデータ(オートコミットされた物も含む)については、
既に書き込まれているので、基本的には元に戻せません。


まだコミットもロールバックもされていない処理がある状態で、
アプリケーション側からの接続が切れた場合、サーバーそのものが正常なのであれば、
クライアントの切断が通知された時に、未処理のトランザクションがすべてロールバックされます。


また、アプリケーション側ではなく、サーバー側が予期せぬシャットダウンを起こした場合は、
リストアの方針によって、ロールフォワードするかどうかを決定します。

https://social.msdn.microsoft.com/Forums/sqlserver/ja-JP/8285f6cb-331d-4924-8348-d60a88f5c329/12487125401247912505125401247312398125251246412501124491245212?forum=sqlserverja
引用返信 編集キー/

このトピックをツリーで一括表示


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

このトピックに書きこむ