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;
}
(ここまで)
お礼
早速の回答ありがとうございます。 どこかで「やっぱり$resultではないよなぁ」と思いつつ、情けないことに他に思いつきませんでした。おかげさまで解決です。 現在はとりあえず動作確認最優先なので、XSS対策等は後回しにしているのですが、運用段階ではきちんと実装させたいと思います。