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

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

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

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

PHP

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

Q&A

解決済

1回答

15840閲覧

mysqlでデータ更新直後に参照しても更新後の値が取得できない

okap

総合スコア11

MySQL

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

PHP

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

0グッド

2クリップ

投稿2017/10/27 09:03

編集2017/10/30 10:43

Mysqlのinnodbとphpを使っています。

現在Mysqlの勉強中なのですが
下記のようなプログラムを書いた時に
『//ユーザーデータ取得③』で$userDataの中身はarray( userId => '1234', userName => 'かきくけこ');になっていて欲しいのですが'あいうえお'のままとなってしまいます。
プログラム終了後にdbの値を確認すると'かきくけこ'に更新されています。

$userId ='1234'; $afterUserName ='かきくけこ'; //ユーザーデータ取得① ★参照用DBに接続★ $userData = getUserData($userId); //$userDataの中身はarray( userId => '1234', userName => 'あいうえお'); //ユーザーデータ更新② ☆更新用DBに接続☆ updateUserData($userId,$afterUserName); //$userDataの中身のuserNameを'かきくけこ'に更新 //ユーザーデータ再取得③ ★参照用DBに接続★ $userData = getUserData($userId); //$userDataの中身がarray( userId => '1234', userName => 'あいうえお');のまま・・・

参照用のDBサーバと更新用のDBサーバは別のもので、クエリログを見ると接続識別子も参照時のものと更新時のものは別IDになっていました。
下記のように書き換えると『//ユーザーデータ取得③』で$userDataの中身はarray( userId => '1234', userName => 'かきくけこ');になっていた・・

$userId ='1234'; $afterUserName ='かきくけこ'; //ユーザーデータ取得① ★参照用DBに接続★ $userData = getUserData($userId); //$userDataの中身はarray( userId => '1234', userName => 'あいうえお'); //ユーザーデータ更新② ☆更新用DBに接続☆ updateUserData($userId,$afterUserName); //$userDataの中身のuserNameを'かきくけこ'に更新 //ユーザーデータ再取得③ ☆更新用DBに接続☆ $userData = getUserData($userId); //$userDataの中身がarray( userId => '1234', userName => 'あいうえお');のまま・・・

なぜこうなるのかググったりしていろいろ調べたところ「DBインスタンス」「スレッド」「ロック」と言われるものが関係してるのかな??と予想し、
私の中での結論は
「異なるスレッドで更新された内容はスレッドを再度作らないと取得できない。自スレッドでの更新内容はすぐに取得できる・・・・?????」
となりました。

この結論はあっているのでしょうか・・・?

周りに聞ける人もおらずそもそも「DBインスタンス」「スレッド」「ロック」等もいまいち理解しきれていない(ググってもちょっと難しかった・・)ので
間違っている or 補足できそうなところがあれば教えて頂きたいです・・・

>miyahanさん
説明が不十分で申し訳ありません・・
ソースコードの公開はちょっと厳しいです・・すみません。。
「updateUserData」はユーザーのデータをupdateする関数で「getUserData」がユーザーデータを取得する関数になります。

>kei344さん
ご指摘ありがとうございます・・!
その機能を知りませんでした・・確かにそっちの方が見やすいです・・
今後はそのようにします!

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

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

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

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

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

miyahan

2017/10/28 02:11 編集

updateUserData と getUserData がどのような動きをしているかわからないので答えようがありません。(内部でキャッシュしているような挙動ですが)2つの関数のソースコードは開示できますか?
kei344

2017/10/30 02:01

質問文のコードはそれぞれコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
guest

回答1

0

ベストアンサー

これが全てですね。

参照用のDBサーバと更新用のDBサーバは別のもので、クエリログを見ると接続識別子も参照時のものと更新時のものは別IDになっていました。

更新してもcommitされていなければDB反映はまだ終わっていませんので、すぐ参照しても前のデータのままです。

反映させてから読みたいなら自分でcommitすれば良いので
「トランザクション」「commit」などで検索してもらえれば分かるかと思います。

投稿2017/10/27 11:31

yuki-saito

総合スコア928

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

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

okap

2017/10/30 01:49

ご回答ありがとうございます! 「ユーザーデータ更新②」の後にcommitはしてました。。情報が足りておらず申し訳ございませんでした・・ 作成済みのスレッドに、他スレッドで更新されたデータは即反映されないのでしょうか・・??
yuki-saito

2017/10/30 01:53

DBサーバが別物ということですが、更新してから再取得するのは同じDBサーバですよね? それともDB更新したサーバから取得用のサーバにレプリケーション等をしているということでしょうか。 だとしたら、レプリケーションされるまでは再取得しても取れないですね。
okap

2017/10/30 03:51

ご回答ありがとうございます! 今はテスト環境なので同じサーバで試しています。なのでレプリケーションは張ってないです! 本番環境ではサーバ自体別にしてレプリケーションを張るためプログラム的には参照用と更新用で別のDB インスタンスを作成するようにしています! commitしたら即レプリケーションされるわけではないとは思うのですが、その場合下記①②どちらかなのかな?と思っておりまして更新用のインスタンスからは更新後の値が取得できているので挙動的に恐らく②に近い感じなのかな・・?と思っているのですが・・認識合ってそうでしょうか・・?フワフワした質問ですみません・・ ①単純に処理が追いついてない。 ②そもそもmysqlの仕組み的に更新用のスレッドでコミットしてもそのスレッドを閉じるまではレプリケーションされない。もしくはレプリケーションされてから作成されたスレッドでないとデータ取得できない。
yuki-saito

2017/10/30 04:05

設定を全て確認した訳ではないので下手なことは言えないのですが、インスタンスが違えばデータが取れないのはその通りです。 レプリケーションタイミングも設定次第ではあるのでしょうけれども、少なくてもレプリケーションが終わらなければデータは見れないでしょう。 更新後すぐに参照をしなければいけないとして、本当の参照用のDBインスタンスから持って来ないといけないのでしょうか? その辺りは少し疑問ですが、考え方は合っていると思うのであとは処理をどうするかだと思います。
okap

2017/10/30 05:14

ご回答ありがとうございます! 更新後すぐに参照する方法は「参照時に更新で使ったインスタンスを使用する」「更新後の値はDB参照せずにPHP側でゴニョゴニョする」など回避策は考えていたのですがDBの仕組みのようなところがあやふやで気になったので質問させて頂きました! 『インスタンスが違えばデータが取れないのはその通りです。』というのが知りたかったです! 質問ばかりで本当に申し訳ないのですが、、、 「インスタンス違えばデータが取れない」理由も教えて頂くことは可能でしょうか・・? 最新のデータを取ってこれないというのは各インスタンス毎にインスタンス生成時のデータをどこかに保持しているのでしょうか・・?この辺りがググっても見つけることができなかったです・・
yuki-saito

2017/10/30 05:28 編集

はい、もちろんそうです。 処理の順番を考えてみてください。 ①インスタンスを使った更新したいデータを設定する。 ②コミットしてDBに反映させる。 もしインスタンス毎にデータを保持していないとすれば①の時点で更新データはどこにあるのでしょう。 当然インスタンス内にデータを持っていて、コミットされればそれをDBに書き込みに行くということです。
okap

2017/10/30 10:09

URLまでありがとうございます! 確かにそれがないとロールバック等もできないのですね・・ 例えばそのインスタンスのDBに100テーブルあって全テーブルの合計レコード数が1億レコード存在してた場合、 インスタンス毎に100テーブル(1億レコード)分のデータを保持してるのでしょうか・・?100人のユーザーがアクセスしてインスタンス生成した場合、膨大なデータなのでそれをプログラム側でインスタンス生成する度に各インスタンスが1億レコード分のデータ保持してるというのが結構大変そうなことだと思ったのでちょっと腑に落ちなかったのですがそういう仕組みなのですよね・・?
yuki-saito

2017/10/30 11:22 編集

必要なものがあるだけです。 UPDATEなら設定したデータのみ。SELECTなら取って来たデータのみ。 「じゃあそれが物凄い数だったら?」って話になると思うので先に言っておくと・・・ メモリが足りずプロセスが落ちます。 そういうクエリは打ってはいけないということです。
okap

2017/10/31 01:54

なるほどです!!必要な分(selectしてたらselect結果、updateだったら多分update対象のデータ?)だけをインスタンス毎に保持しておくというのは凄く納得できました! すっきりしました!長々と本当にありがとうございます!大変勉強になりました!!
yuki-saito

2017/10/31 01:56

少しでもお役に立ててよかったです^^
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問