質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

450閲覧

マスタースレーブのDB構成でモジュールの独立性を担保する

kurekurekure

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

3クリップ

投稿2018/12/28 13:40

前提・実現したいこと

NetFramework(C#)でユーザー情報を操作するAPIを作成しています。
データベースはMySQLで、マスターと複数のスレーブを持つ構成です。

API処理の中では複数の処理(モジュールと呼びます)を呼び出し、
それぞれが都度データベースから書き込んだり読み込んだりをしています。

ところが上記構成により、マスター書き込みの後スレーブへリレーションされるため、
1つ目のモジュールで更新したユーザー情報が、2つ目のモジュールでスレーブ反映される前に読み込まれ、
ユーザー情報がロールバックする状態が発生しうる状況となっています。
当然、モジュールの呼び出し順でも結果が変わる可能性があります。

モジュールの独立性、ユーザー情報のロールバックを防ぐためには、
一般的にはどのような設計が正しいのでしょうか?

特に言語は問いません。
ロジック的な解決が望ましいですが、あるいはデータベース構成を見直す、Redis等のキャッシュサービスを挟むなどでも構いません。

ご意見ご教授いただきたく質問いたしました。

参考

各モジュールはコンパイルされていないのでコード変更は可能です。
モジュールのデータベース読み込みには独自のORMマッパーを利用しています。
ORMマッパーからMySQL接続までに独自のキャッシュシステムを組み込む余地もあります。
あるいはORM呼び出し処理そのものをキャッシュシステムを通すよう変更することも可能ではあります。
(その場合はすべての呼び出しコードを書き換える必要があります。)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ssasaki

2018/12/30 10:02

他の方の回答を見る限り、マスタースレーブ構成による問題ではなく単なる同時アクセスの問題のように思えますが、そうなのでしょうか? そうではない場合、気になる点としてはスレーブでも更新が入るのでしょうか? また、フロントの方も複数台のサーバもしくはプロセス構成なのでしょうか? レプリケーションやクラスタ構成の問題の解決は、システム全体の構成が関係してくるので可能な限り全貌を明らかにした方が回答が付きやすいかと思います。
guest

回答3

0

ベストアンサー

ロジック的な解決が望ましいですが、あるいはデータベース構成を見直す、Redis等のキャッシュサービスを挟むなどでも構いません。

アプリケーション側で対処することは困難なので、データベース構成を見直すことをお勧めします。
MySQL Clusterならアプリケーション側の変更は最小限になると思います。

追記:一応確認ですけど
・レプリケーション構成で複数のスレーブを持つ
・複数個所からの更新が多い
・現状パフォーマンスの問題で楽観的ロックにしている
ってことですよね?

投稿2018/12/29 01:52

編集2018/12/29 08:54
hihijiji

総合スコア4150

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurekurekure

2018/12/30 05:49

楽観的ロックで調べたところ、私の言いたかったそのものの問題が見つかりました。 https://qiita.com/NagaokaKenichi/items/73040df85b7bd4e9ecfc 他社様の参考画像で恐縮ですが、楽観的ロックよりも手前の、排他制御を一切していない状態です。 実績のある旧システムを引き継いて、新システムを作成しているのが理由です。 旧システムでは単に「単一のAPIでは同一のデータの更新は行わない」というプログラムルールでのみ解決しています。 「次の連続したAPIが来るまでにはスレーブ同期は終わっている」という条件も付きます。 現在は私がコードを監視して正しく動くよう注意しているのですが、いずれは重篤な問題を引き起こすのは想像にたやすいです。 マスターへの書き込みだけであればトランザクションにより対策されています。 ところが、オリジナルのORMマッパーは必ずスレーブからデータを取得してきます。 この際、スレーブのレプリケーション遅延に対しては特にロックは行われておらず、古いデータでも気にせず取り出して、同一データへの更新があればマスタートランザクション終了後に古いデータで上書きしてしまう仕様です。(今はそれをしないように注意しているだけです。) 後ほど質問文は追記しておきます。 出来ない、というだけでも重要な情報です。 真摯なご回答有り難うございました。
hihijiji

2018/12/31 05:44

レプリケーションは基本的に非同期でデータの複製を行う仕組みですから、スレーブにおいて更新が起きるのはマスター側の更新のCOMIT後になります。 これは非同期である以上不可避です。 レプリケーション構成で同期で更新を行うとパフォーマンスはとっても悪くなりますから、その選択肢は無いと思います。 ってことでクラスタ構成にすることをお勧めします。 楽観的ロック云々はこの構成に限り悲観的ロックよりもマシかな?と思ったので書いたのですが、根本的な解決にならないので忘れてください。
guest

0

マスターと複数のスレーブを持つ構成

その意味が理解できていませんが、テーブル間に外部キー制約が張ってあるということでしょうか?

マスター書き込みの後スレーブへリレーションされるため、1つ目のモジュールで更新したユーザー情報が、2つ目のモジュールでスレーブ反映される前に読み込まれ、ユーザー情報がロールバックする状態が発生しうる状況となっています。

そこも理解できていませんが、例えば(あくまで例えば)、

(1) データベースに Customers と Orders テーブルがある。

(2) Customers テーブルは CustomerID を主キーとして持ち、Orders テーブルは CustomerID を外部キーとして持っている。

(3) 新しい顧客から注文があった場合は、先に新しい顧客レコードを Customers テーブルに Insert してから、注文レコードを Orders テーブルに Insert しなければならない。

(4) 質問者さんのケースでは上記 (3) の順序が逆になって例外がスローされロールバックされてしまう。

・・・と言うような話と想像していますがいかがですか? 想像が違う場合は、上の例にならって詳しく書いてください。上記の程度に具体的に書いていただけないと、少なくとも自分には質問者さんの状況・問題が分かりません。

想像が合っているとすると、階層更新を行う手段を実装するということになるはずです。

質問者さんのアプリで使えるかどうか分かりませんが、Visual Studio 2008 以降では、階層更新を実現する TableAdapterManager クラスが追加で自動生成されるようになりました。

詳しくは以下の記事を見てください。

TableAdapterManager
http://surferonwww.info/BlogEngine/post/2011/12/21/TableAdapterManager.aspx

質問者さんのアプリで型指定された DataSet + TableAdapter + TableAdapterManager が使えなくても、Visual Studio が自動生成したコードを見れば参考になるかもしれません。

上に紹介した記事は SQL Server の例ですが、MySQL でも Visual Studio のウィザードを利用して型指定された DataSet + TableAdapter + TableAdapterManager は自動生成できます。

ただし、Visual Studio のウィザードが使う MySql.Data.dll のバージョン 6.9.8 と、GAC の MySql.Data.dll のバージョン 6.9.9 に不一致があって、それが原因でウィザードが期待通り動かないという不具合がありましたので注意してください。

詳しい説明と解決方法は以下の記事を見てください。

MySQL での TableAdapter 構成ウィザード不具合
http://surferonwww.info/BlogEngine/post/2018/02/10/tableadapter-configuration-wizard-does-not-work-properly-for-mysql.aspx

【追記】

下の 2018/12/30 17:43 の私のコメントで、

同時実行制御の話だったようですね。楽観的同時実行制御で良ければ、上の回答で紹介した、型指定された DataSet + TableAdapter + TableAdapterManager を Visual Studio のウィザードで生成する際、それを設定するオプションがあります。それも検討されてはいかがでしょう? ご参考に回答欄に画像を貼っておきます。

と書きましたが、その画像を以下に貼っておきます。

イメージ説明

投稿2018/12/29 01:50

編集2018/12/30 08:46
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurekurekure

2018/12/30 05:57

外部キー制約については行っておりません。 状況については他者様のサイトで恐縮ではありますが、 https://qiita.com/NagaokaKenichi/items/73040df85b7bd4e9ecfc こちらの「同時アクセスによる不整合」の例そのもので、排他制御を全くしていない状態です。 旧システムの引き継ぎであるためで、そちらでは単に「単一のAPIでは同一のデータの更新は行わない」というコーディングルールで解決しています。 マスターDB単独でのトランザクション処理はしっかり行っているので、特に例外やロールバックが発生することはなく動作しています。 続く処理ではレプリケーションサーバーからの遅延した古い情報を読み込み、それにより先に書き換えたデータを上書きする可能性があります。 TableAdapterManager、参考とさせていただきました。 どうやら今は、それ以前の問題である気がします。 真摯なご回答有り難うございます。
退会済みユーザー

退会済みユーザー

2018/12/30 08:43

同時実行制御の話だったようですね。楽観的同時実行制御で良ければ、上の回答で紹介した、型指定された DataSet + TableAdapter + TableAdapterManager を Visual Studio のウィザードで生成する際、それを設定するオプションがあります。それも検討されてはいかがでしょう? ご参考に回答欄に画像を貼っておきます。
kurekurekure

2019/01/07 01:49

どうしても元の実績のあるコードを活かす必要があり、独自ORMマッパーの制約から離れられません。 知見として面白かったので参考とさせていただきました。 TableAdapterManager を使った.NetのORMマッパー。
guest

0

正月前に結構頑張って質問文を編集したつもりでしたが、不慣れなため反映されておりませんでした。

ご回答から現在の設定を改めて見直しましたところ、
私達のシステムはどうやら一般的なマスタースレーブの非同期レプリケーションであって、
その場合は排他制御を実現するのは難しいことが改めてわかりました。

今回はコードを自由に操作できることから、ORMマッパーからのデータ取得手前でキャッシュシステムを挟むソフトウェア対応とするつもりです。

MySQLクラスタ構成は実績がないため、コード修正が複雑になりそうであれば検討していきたいと思います。
同期レプリケーションという手段もあることも把握しましたが、こちらはご指摘の通り、速度の問題が出てくるのは目に見えています。

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

投稿2019/01/07 01:50

kurekurekure

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問