在select上锁定mysql数据库表行

时间:2013-11-25 22:33:12

标签: php mysql session session-management

我正在为用户之间的Web服务管理一个无状态会话池 因此,当用户请求Web服务时,他启动会话并且响应超时为5秒,因此他可以保持会话最多5秒。第二个用户进来并系统检查是否有可用的会话然后使用它。

现在我有一个问题。当让我们说有可用的会话时,用户A来,系统检查它是否超过5秒前使用,给用户A,同时另一个用户点击并系统检查会话是否超过4秒前使用,分配用户B.
现在,使用相同会话和系统的用户都失败了。

我已尝试选择更新命令以锁定它 我已经尝试过第一个用户选择更新上次使用的时间,但这不起作用(我认为第二个用户同时击中系统)
有人可以就此提出建议。

代码:检查db中的会话(如果可用),然后选择它或插入新的

//get 25 sessions from database order by lastqueryDate
$session = $sessionObj->select('session', '*', '', 'LastQueryDate DESC', '25');

$available_session = array();
//if sessions available, get rows from getResult
if ($session) {
    $session_Data = $sessionObj->getResult();
    //now get session which is sitting there more than response time out              
    $available_session = $sessionObj->getAvailableSession($session_Data);
}
//if there is any, use it. otherwise create new session and save in database
if (!$available_session) {
    $auth->securityAuthenticate();

    $header = $auth->getHeaders();
    $sequence = (int) $header['Session']->SequenceNumber + 1;
    $values[] = $header['Session']->SessionId;
    $values [] = $sequence;
    $values [] = $header['Session']->SecurityToken;

    $rows = "SessionID,SequenceNo,Security_token";
    if ($sessionObj->insert('session', $values, $rows)) {

        $available_session['Session']->SessionId = $header['Session']->SessionId;
        $available_session['Session']->SequenceNumber = $sequence;
        $available_session['Session']->SecurityToken = $header['Session']->SecurityToken;

    }
}

检查db中会话可用性的函数:

public function getAvailableSession($session_data) {
    $available_session = array();
    foreach ($session_data as $key) {            
        if (!is_array($key)) {
            $key = $session_data;
        }


        $date = date('Y-m-d h:i:s a', time());
        $now = new DateTime($date);
        $last_query_time = new DateTime($key['LastQueryDate']);
        $dteDiff = $last_query_time->diff($now);
        $difference = $dteDiff->format("%H:%I:%S");
        //if response time out is smaller than session used last. then pick it.
        if (RTO <= $difference) {

            $available_session['Session']->SessionId = $key['SessionID'];
            $available_session['Session']->SequenceNumber = $key['SequenceNo'];
            $available_session['Session']->SecurityToken = $key['Security_token'];
            // run update to update lastqueryDate as its default value set to current time stamp
            $session_value = $key['SessionID'];
            $rows['SequenceNo'] = $key['SequenceNo'];
            $where[0] = "SessionID";
            $where[2] = "'" . $session_value . "'";                
            $this->update('session', $rows, $where);
            return $available_session;
        }
    }
    return false;
}

一旦我发现会话闲置超过5秒,我就会更新数据库。

1 个答案:

答案 0 :(得分:0)

开放交易。发出“select ... for update”查询以获取会话数据。在脚本结束时提交事务。