基于PHP数据库的会话数据
我正在尝试设计一个会话处理程序,它使用数据库来存储详细信息 其中一点是,如果当前正在使用会话数据,那么我不希望加载它们(直到第一个脚本完成并更新数据) 我有一个基本的类来完成这项工作,它似乎正在工作,下面是一个小测试脚本:-基于PHP数据库的会话数据,php,mysql,session,Php,Mysql,Session,我正在尝试设计一个会话处理程序,它使用数据库来存储详细信息 其中一点是,如果当前正在使用会话数据,那么我不希望加载它们(直到第一个脚本完成并更新数据) 我有一个基本的类来完成这项工作,它似乎正在工作,下面是一个小测试脚本:- <?php class MySessionHandler implements SessionHandlerInterface { private $db = null; public function open($savePath, $sess
<?php
class MySessionHandler implements SessionHandlerInterface
{
private $db = null;
public function open($savePath, $sessionName)
{
$host = 'localhost';
$user = 'root';
$pass = '';
$name = 'em_sessions';
$this->db = new mysqli($host, $user, $pass, $name);
return true;
}
public function close()
{
return true;
}
public function read($session_key)
{
$this->db->autocommit(FALSE);
if($stmt = $this->db->prepare("SELECT data FROM sessions WHERE session_key = ? FOR UPDATE"))
{
$stmt->bind_param('s', $session_key);
$stmt->execute();
echo $stmt->error." - ".$stmt->errno."<br />";
$retry = 0;
while ($stmt->errno == 1213 and $retry++ < 20)
{
usleep(50);
$stmt->execute();
echo $stmt->error." - ".$stmt->errno."<br />";
}
$stmt->store_result();
$stmt->bind_result($data);
$stmt->fetch();
}
else
{
echo "Unable to prepare statement ".$this->db->error."<br />";
}
return $data;
}
public function write($session_key, $data)
{
$time = time();
if($stmt = $this->db->prepare("INSERT INTO sessions (set_time, data, session_key) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE set_time=VALUES(set_time), data=VALUES(data)"))
{
echo "Written(".time().")<br />";
$stmt->bind_param('iss', $time, $data, $session_key);
$stmt->execute();
$this->db->commit();
}
else
{
echo "Unable to prepare statement ".$this->db->error."<br />";
}
return true;
}
public function destroy($session_key)
{
if($stmt = $this->db->prepare("DELETE FROM sessions WHERE session_key = ?"))
{
$stmt->bind_param('s', $session_key);
$stmt->execute();
}
else
{
echo "Unable to prepare statement ".$this->db->error."<br />";
}
return true;
}
public function gc($maxlifetime)
{
if($stmt = $this->db->prepare("DELETE FROM sessions WHERE set_time < ?"))
{
$old = time() - $max;
$stmt->bind_param('s', $old);
$stmt->execute();
}
else
{
echo "Unable to prepare statement ".$this->db->error."<br />";
}
return true;
}
}
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
echo session_id()."<br />";
echo "<a href='http://localhost/TestArea/session_test.php'>Do Me</a><br />";
if (!array_key_exists('cnt', $_SESSION))
{
echo "No session cnt found so initialising<br />";
$_SESSION['cnt'] = 0;
}
echo "Page called ".++$_SESSION['cnt']." times (".time().")<br />";
sleep(2);
session_write_close();
sleep(2);
echo "Ended(".time().")<br />";
这是一个有趣的问题,这里有一个长期的尝试,试图找出问题可能是什么——检查您是否正在执行流水线HTTP请求。您还没有说您使用了哪种浏览器或哪台服务器有问题,可能他们正在管道传输HTTP请求,这将把责任转移到与您怀疑的完全不同的部分(这部分是浏览器Web服务器通信,而不是您的脚本)。如果你能查出来并排除它(除非是罪魁祸首),那将有助于进一步调试。@N.B.-为这个想法干杯。它似乎与浏览器无关,其行为与Opera、Chrome和Firefox中的行为相同。就服务器而言,它在我的Windows机器上的WAMP服务器上以及上传到Linux机器上时的行为都是相同的。然而,它已经触发我尝试其他东西。我还保存了脚本的开始时间(在会话开始之前)并将其输出。当第一次运行完成时,脚本的第二次和后续运行具有此开始时间。似乎整个脚本都被阻止了,不仅仅是会话。是的,这就是管道的作用。这是Apache的默认行为。排除这种情况的一种方法是实际执行来自两台不同机器(所有不同管道)的请求。我之所以提出这个建议,是因为我在下载一个文件时遇到了一个问题,我以前一直在编码这个文件。这很奇怪,因为我不能一次下载两个文件(通过点击中间的链接)。第二个总是在第一个完成后开始。管道是罪魁祸首,而不是我最初认为的代码。谢谢。这是一个我几乎一无所知的领域。为什么这会影响第二个脚本,而不会影响后续脚本?知道我怎么关掉吗?或者我是否需要发送一个标题来关闭连接(这在一般情况下是不切实际的)?@N.B.-作为旁白,刚刚选中,虽然Firefox确实显示了这个问题,但在我的Firefox配置中,管道未启用。
CREATE TABLE IF NOT EXISTS `sessions` (
`set_time` int(11) NOT NULL,
`session_key` char(32) NOT NULL,
`data` longtext NOT NULL,
PRIMARY KEY (`session_key`),
KEY `set_time` (`set_time`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;