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

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

ただいまの
回答率

90.46%

  • PHP

    24600questions

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

  • MySQL

    7155questions

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

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 3,090

okap

score 3

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miyahan

    2017/10/28 11:04 編集

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

    キャンセル

  • kei344

    2017/10/30 11:01

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

    キャンセル

回答 1

checkベストアンサー

+1

これが全てですね。

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/30 10:49

    ご回答ありがとうございます!

    「ユーザーデータ更新②」の後にcommitはしてました。。情報が足りておらず申し訳ございませんでした・・

    作成済みのスレッドに、他スレッドで更新されたデータは即反映されないのでしょうか・・??

    キャンセル

  • 2017/10/30 10:53

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

    キャンセル

  • 2017/10/30 12:51

    ご回答ありがとうございます!

    今はテスト環境なので同じサーバで試しています。なのでレプリケーションは張ってないです!
    本番環境ではサーバ自体別にしてレプリケーションを張るためプログラム的には参照用と更新用で別のDB
    インスタンスを作成するようにしています!

    commitしたら即レプリケーションされるわけではないとは思うのですが、その場合下記①②どちらかなのかな?と思っておりまして更新用のインスタンスからは更新後の値が取得できているので挙動的に恐らく②に近い感じなのかな・・?と思っているのですが・・認識合ってそうでしょうか・・?フワフワした質問ですみません・・

    ①単純に処理が追いついてない。
    ②そもそもmysqlの仕組み的に更新用のスレッドでコミットしてもそのスレッドを閉じるまではレプリケーションされない。もしくはレプリケーションされてから作成されたスレッドでないとデータ取得できない。

    キャンセル

  • 2017/10/30 13:05

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

    キャンセル

  • 2017/10/30 14:14

    ご回答ありがとうございます!

    更新後すぐに参照する方法は「参照時に更新で使ったインスタンスを使用する」「更新後の値はDB参照せずにPHP側でゴニョゴニョする」など回避策は考えていたのですがDBの仕組みのようなところがあやふやで気になったので質問させて頂きました!
    『インスタンスが違えばデータが取れないのはその通りです。』というのが知りたかったです!

    質問ばかりで本当に申し訳ないのですが、、、
    「インスタンス違えばデータが取れない」理由も教えて頂くことは可能でしょうか・・?
    最新のデータを取ってこれないというのは各インスタンス毎にインスタンス生成時のデータをどこかに保持しているのでしょうか・・?この辺りがググっても見つけることができなかったです・・

    キャンセル

  • 2017/10/30 14:27 編集

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

    キャンセル

  • 2017/10/30 14:30

    考え方としてはこのページが分かりやすいですかね。
    http://mti.hatenablog.com/entry/2017/07/23/225631

    キャンセル

  • 2017/10/30 19:09

    URLまでありがとうございます!

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

    キャンセル

  • 2017/10/30 20:22 編集

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

    キャンセル

  • 2017/10/31 10:54

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

    キャンセル

  • 2017/10/31 10:56

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

    キャンセル

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

  • ただいまの回答率 90.46%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • PHP

    24600questions

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

  • MySQL

    7155questions

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