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

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

解決済

1回答

4401閲覧

mysqlで接続数を任意の数までに制限したい。

退会済みユーザー

退会済みユーザー

総合スコア0

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クリップ

投稿2016/11/17 11:18

phpでmysqlにPDOで接続し、接続数を任意の数までに制限したいがうまくいかない。
制限の方法は、接続するとテーブルにアクセスし、任意の数以下のレコード数ならレコードを登録し、その後の処理を実行します。
処理が終われば、レコードをデリートします。
「レコード数が設定した数より少なくない」
という場合のみ処理を終了させたいと考えております。

//プロセス管理用変数 $g_id = -1; //プロセスID(ps_timeテーブルのid列(PK)) $g_set_time = -1; //プロセス取得時間(ps_timeテーブルのtime列) function DataBaseInit(){ $dsn = "mysql:host=127.0.0.1;dbname=".DATABASE_NAME.";charset=utf8"; $username = USER_NAME; //ユーザ名 $password = PASSWORD; //パスワード $db = null; //DBクラス格納場所 function DataBaseInit(){ //グローバル変数の使用宣言 global $db, $dsn, $username, $password; if($db != null) return false; //すでに実体が生成されていれば処理しない try{ $db = new PDO($dsn, $username, $password); //属性設定 $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); } catch(Exception $e){ if(DEBUG_MODE) var_dump($e); return false; //エラーで失敗 } return true; //成功 } function BusyCheck($u_id){ global $db, $g_id, $g_set_time; //グローバル変数 $rtn_val = false; //戻り値用変数(デフォルトでfalse) //DBからデータ取得 $sql = "select * from レコード登録テーブル"; //SQL文(全件取得) $stmt = $db->query($sql); //クエリ送信 $row_cnt = (int)$stmt->rowCount(); //レコード件数取得 //取得したデータのIDチェック //レコード件数がレコード最大数未満の時のみ実行(MAXだと追加できないため) echo 'レコード件数:'.$row_cnt.'<br>'; if($row_cnt < 任意の制限数){ $live_id = $ユニークな文字列; } else { $stmt = null; return false; } //$live_idに-1以外が入っていた場合は以下を実行 $sql = "INSERT INTO ps_time(id, time) VALUES(:id, :time)"; //SQL文設定 //SQL文送信 $stmt = $db->prepare($sql); //グローバル変数に今回送信する値を格納 $g_id = $live_id; //(IDを格納) $g_set_time = time(); //タイムスタンプ格納 //値をセット $stmt->bindValue(':id', $g_id, PDO::PARAM_STR); $stmt->bindValue(':time', $g_set_time, PDO::PARAM_INT); //送信したデータを確定 $result = $stmt->execute(); $stmt = null; var_dump($result); if(!$result){ $rtn_val = false; }else{ //成功したらtrue $rtn_val = true; } return $rtn_val; //失敗ならfalse,成功なら$sem_idを返す } function ProcessDBDelete(){ //グローバル変数の使用宣言 global $db, $g_id; //グローバル変数 //正しい数値が入っているかチェック if($g_id === -1){ return false; //初期値が入っているので処理できずエラー } //$live_idに-1以外が入っていた場合は以下を実行 $sql = "DELETE FROM ps_time WHERE id = :uid "; //SQL文送信 $stmt = $db->prepare($sql); //変数送信 $stmt->bindValue(":uid", $g_id, PDO::PARAM_INT); //送信したデータを確定して、結果を返して終了 try { return $stmt->execute(); } finally { $stmt = null; } } DataBaseInit(); if(!BusyCheck($u_id)) { // u_idはユニークな文字列 // プログラムを終了させる処理 } ・ ・ // 行いたい処理処理 ・ ProcessDBDelete()

このような感じで処理をかいています。
複数同時にプログラムを実行させても、一つのデリートが終わるまで、次の待っているインサートが始まりません。
なので、テーブルを見ていると前のレコードが消えたと同時に次のレコードがインサートされ、待っている状態になっています。
これを待たずに制限いっぱいのレコードのときは処理を終了させるようにできないでしょうか?

mysql

1mysql > show variables like 'max_connections';

で同時接続数を確認しましたところ、100を超える数字になっており同時接続が問題無いように感じました。
同時にプログラムを実行させるときに、違うPC、違うIPでも試しましたが、常に待っている状態でした。
一つ気になることが、私一人で複数実行したときは最大で一つしかレコードが入りませんでした。
同じIPでは、一つのプロセスが終わるまで次のプロセスが実行されないのでしょうか?

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

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

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

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

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

popobot

2016/11/17 22:15 編集

接続数を制限するやり方としては、max_connectionsを使う方法などが一般的だと思うのですが、自前で管理したいということですか? このやり方だと想定外のエラー発生時などにdeleteの処理が実行されず、接続は切れているけど、接続中の扱いになったりして、結構危険な処理だなぁと思いました。
KiyoshiMotoki

2016/11/18 11:58

質問内容が矛盾しています。「同じIPでは、一つのプロセスが終わるまで次のプロセスが実行されないのでしょうか?」という一方で「違うPC、違うIPでも試しましたが、常に待っている状態でした。 」とも言っているため、結局、同時に実行できたケースが記載されていません。
KiyoshiMotoki

2016/11/18 12:01 編集

もし、「違うPC、違うIPでも試しました」の意味が「PC、IPを変えた上で、1つのPC・IPから同時に実行してみた」という意味でしたら、プログラムの実行方法に問題がある可能性も考えられます。(PHPスクリプトに対して、同時実行を防止する制御が入っているなど。)
KiyoshiMotoki

2016/11/18 12:02

そのため、PHPスクリプトの実行環境も追記すると、具体的な回答を得やすくなるかと思います。
guest

回答1

0

ベストアンサー

処理の実行をプロシージャで行うことにし
トランザクションを設定した上でコミットする前に当該テーブルをチェックし
想定外であればロールバックすればよいのでは?

投稿2016/11/17 13:00

yambejp

総合スコア114769

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

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

退会済みユーザー

退会済みユーザー

2016/11/20 14:45 編集

同僚と話し合った結果この方法で解決することができました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問