- 締切済み
PHPをまたいだロックの管理
現在、PHPとMySQLを使ってデータ管理のプログラムを構築しています。 その中で、複数のPHPをまたいで同じデータテーブルを使おうとしたときに デッドロックが起きないようロック用のテーブルを作り、 データテーブルを編集するときにテーブルロック判定をかけようとしているのですが、 エラーが出てしまい上手くいきません。 以下に現状のプログラムを置いておきます。 もしお手隙でしたら、どなたかアドバイスいただけますでしょうか。 どうぞよろしくお願いいたします。 (ここから) $conn = @mysql_connect(DB_HOST, DB_NAME, DB_PASS); if (!$conn || !mysql_select_db(DB_MASTER, $conn)){ echo "DBopenError:DBオープン時エラーが発生しました。<DB>"; } mysql_set_charset('utf8', $conn); mysql_query('SET AUTOCOMMIT = 0;', $conn); mysql_query('START TRANSACTION;', $conn); // テーブルのロック mysql_query('LOCK TABLES tbllock WRITE, tbldata WRITE, temp WRITE;', $conn); // ロックの判定 $lock = checkLock($conn, 'tbldata', $sessID); // テーブルのロックを解除 mysql_query('UNLOCK TABLES;', $conn); $cnt = 0; while ($lock === false) { if ($cnt > 10) break; sleep(1); $lock = checkLock($conn, 'tbldata', $sessID); $cnt++; } if($lock === false) die('タイムアウトしました。'); else{ /* データ編集処理 */ } if (mysql_errno($conn)) mysql_query('COMMIT;', $conn); else mysql_query('ROLLBACK;', $conn); mysql_close($conn); //------------------------------------------------------------------ // 編集ロックチェック //------------------------------------------------------------------ function checkLock($dbID, $selTable, $oldsid) { $sqlstr = sprintf("SELECT * FROM tbllock WHERE tblName = '%s' FOR UPDATE;", $selTable); $result = mysql_query($sqlstr, $conn); $num = mysql_numrows($result); $flg = false; if ($num > 0) { if(mysql_result($result, 0, 'enable') === '0' || strlen(mysql_result($result, 0, 'lockUser')) === 0) $flg = true; else { if(in_array(mysql_result($result, 0, 'lockUser'), $oldsid)) $flg = true; else { $lockedDate = strtotime('-5 minute'); if (strtotime(mysql_result($result, 0, 'lockedDate')) < $lockedDate) { $sqlstr = sprintf("UPDATE tbllock SET enable = '0' WHERE tblName = '%s';", $selTable); $result = mysql_query($sqlstr, $dbID); $flg = true; } } } } if ($flg === true) { $sqlstr = sprintf("UPDATE tbllock SET lockUser = '%s', lockedDate = NOW(), enable = '1' WHERE tblName = '%s';", session_id(), $selTable); $result = mysql_query($sqlstr, $dbID); return true; } else return false; } (ここまで)
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- athanasius
- ベストアンサー率37% (361/964)
イマイチ、分からないのですが、 MySQL でも トランザクションをサポートしている innoDB というものが ありますが、それをつかって、トランザクションで処理すれば、テーブルをロックする必要も ないので、スループットも上がると思いますが、なぜ使わないのでしょうか? innoDBなら、Windowsでもついているくらいなので、標準だと思っていますが。 前に SUNのセミナーなんかだとISAM は、今後メンテしないとか言っていたくらいなので、 innoDB を使うのが世間的なものだと、私は思っていました。
お礼
回答、どうもありがとうございました。 結局、別の方法でアクセス制限をかけました。 なんとかこの方法でやっていけそうなので、 質問はこれで締め切りたいと思います。
補足
回答ありがとうございます。 トランザクションを利用して処理、ですね。 ISAMではなくInnoDBを利用しているのですが、上手く特性を活用しきれていなかったようです。 現在のプログラムの流れが、簡単にまとめますとこのようになっておりまして、テーブルへの保存を行うときは、自己呼び出しをしてパラメータを渡す仕組みになっています。 パラメータ = $_POST if(パラメータ === 保存){ データテーブルを空にする データテーブルに一時テーブルのデータをコピーする 一時テーブルを空にする 一時テーブルの中身を表示 } elseif (パラメータ === 一時テーブルのデータ全消去) { 一時テーブルを空にする 一時テーブルの中身を表示 } elseif (パラメータ === CSV読込) { CSV読込 一時テーブルに保存 一時テーブルの中身を表示 } else { 一時テーブルを空にする データテーブルから一時テーブルにデータをコピー 一時テーブルの中身を表示 } 自己呼び出しをしてページを読み込みしなおすときに、テーブルのロックが外れてしまわないようにしたいのです。 ロックはページの読み込みをしなおすと外れてしまうと思っていたので、テーブルロック状態確認用のテーブルを作ったのですが、他に方法があるのでしょうか。 少し調べてみます。