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

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

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

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

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

Q&A

解決済

2回答

4578閲覧

【PHP,MySQL】PDOのlastinsertid()は、競合しますか?

sanset

総合スコア186

MySQL

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

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

0グッド

0クリップ

投稿2015/12/01 06:27

phpのPDOのlastinsertid()について、詳しい仕様を教えて頂きたいです。
例えば、下記のような単純なユーザー登録、その後に登録したIDをセッションにいれるような処理を作るとします。

PHP

1// プライマリキーにはAUTO_INCREMENTの「user_id」が存在します。 2$sql = "INSERT INTO users 3 (user_name) 4 values 5 (:user_name)"; 6 7$sth = $pdo -> prepare($sql); 8$sth -> bindValue(':user_name', $name, PDO::PARAM_STR); 9$sth -> execute(); 10$_SESSION['me'] = $pdo -> lastInsertId();

このときに$pdo -> lastInsertId()で、セッションにidを入れてますが、
もしこの処理が各ホストから同時に行われた場合、
本来入るべきIDではなく、別のユーザーのlastInsertId()を取得してしまう場合があるのでしょうか?
マニュアルには「最後に挿入された行の ID」となってますので、低い確率ですが、同時処理とかで別のユーザーのidを取得してしまうのではないかと懸念しております。
どうかご教示お願いいたします。

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

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

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

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

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

guest

回答2

0

【恐らく】競合しません。

MySQLに対してPDO::lastInsertId()を実行すると、【恐らく】DBに対してSELECT LAST_INSERT_ID()というクエリを実行しています。

で、MySQLのリファレンスには、LAST_INSERT_ID()関数で

生成された ID は、接続ごとにサーバー内に保持されます。つまり、関数によって指定されたクライアントに返された値は、そのクライアントによって AUTO_INCREMENT カラムに影響を与える最近のステートメント用に最初に生成された AUTO_INCREMENT 値です。この値は、ほかのクライアントが独自の AUTO_INCREMENT 値を生成した場合でも影響を受ける可能性はありません。この動作によって、各クライアントはほかのクライアントのアクティビティーを気にすることなく、ロックやトランザクションを実行しないで独自の ID を取得できます。

と、記載されているからです。
https://dev.mysql.com/doc/refman/5.6/ja/information-functions.html#function_last-insert-id

※"【恐らく】"部分の確証は、公式の情報からは得ることができませんでした。
テストコードで比較してみた限りでは、PDO::lastInsertId()SELECT LAST_INSERT_ID()の動作は一致していたので
【恐らく】間違いないと思いますが。。

投稿2015/12/01 07:11

編集2015/12/01 07:12
KiyoshiMotoki

総合スコア4791

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

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

sanset

2015/12/04 02:42

ご連絡遅れて申し訳ありません。 詳しい解説まで添えて頂きありがとうございます。 非常に心苦しいのですが、ベストアンサーをつけれるのはおひとりということで、 先にご回答頂いた方をベストアンサーにさせて頂きました。申し訳ありません。 また何かございましたらよろしくお願いします。
KiyoshiMotoki

2015/12/04 02:52

sanset様、ご丁寧な返信ありがとうございます。 お役に立てたなら幸いです。
guest

0

ベストアンサー

結論としては競合しません。
公式の記述がどこにあったか覚えていませんが、

PHP

1// プライマリキーにはAUTO_INCREMENTの「user_id」が存在します。 2$sql = "INSERT INTO users 3 (user_name) 4 values 5 (:user_name)"; 6 7$sth = $pdo -> prepare($sql); 8$sth -> bindValue(':user_name', $name, PDO::PARAM_STR); 9$sth -> execute(); 10sleep(10); 11$_SESSION['me'] = $pdo -> lastInsertId();

という感じで実行した後に10秒意図的に処理を遅らせるスクリプトを用意して、
0. 処理を遅らせるスクリプトを実行
0. 10秒以内に通常のスクリプトを実行
0. 通常のスクリプトの処理完了→結果をログなりに書きだす
0. 処理を遅らせるスクリプトの処理完了→結果をログなりに書きだす
とすれば検証出来るかと思います。

投稿2015/12/01 06:40

tanat

総合スコア18713

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

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

sanset

2015/12/04 02:40

ご連絡遅れて申し訳ありません。 試してみて競合しないことが分かりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問