迅雷不及掩耳盗铃之势申请了Picasa Web Albums 海陀一日归来
Jun 16
作者: 肖建彬 | 可以转载, 转载时务必以超链接形式标明文章原始出处和作者信息及版权声明
网址:http://www.xiaojb.com/archives/it/phpmysqlsession.shtml

使用MySQL保存session会话较files有很多优点:
1) 有利于分布式系统,files只能保存在一台机器上
2) 有利于大访问量的系统,使用files时每个session保存在一个文件中,目录会超级大,查找session文件会比较困难,当然,也可以自己写一个有hash目录的替代。

使用MySQL保存会话首先要创建session表:

  1. CREATE TABLE `sessions` (
  2.   `sid` char(40) NOT NULL,
  3.   `data` text NOT NULL,
  4.   `update` int(10) unsigned NOT NULL default '0',
  5.   UNIQUE KEY `sid` (`sid`)
  6. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

程序如下:

下载: session.php
  1. <?php
  2.  
  3. function sess_open($path, $name) {
  4.         return TRUE;
  5. }
  6.  
  7. function sess_close() {
  8.         return TRUE;
  9. }
  10.  
  11. function sess_read($sid) {
  12.         global $db;
  13.         $query = $db->query("SELECT data FROM sessions WHERE sid='$sid' LIMIT 1",'SILENT');
  14.         if($db->num_rows($query)) {
  15.                 return $db->result($query, 0);
  16.         } else {
  17.                 $db->query("INSERT INTO sessions SET sid='$sid',update=UNIX_TIMESTAMP()",'SILENT');
  18.         }
  19.         return TRUE;
  20. }
  21.  
  22. function sess_write($sid, $data) {
  23.         global $db;
  24.         $data = addslashes($data);
  25.         $db->query("UPDATE sessions SET data='$data',lastupdate=UNIX_TIMESTAMP() WHERE sid='$sid' LIMIT 1",'SILENT');
  26.         return TRUE;
  27. }
  28.  
  29. function sess_destroy($sid) {
  30.         global $db;
  31.         $db->query("DELETE FROM sessions WHERE sid='$sid'",'SILENT');
  32.         return TRUE;
  33. }
  34.  
  35. function sess_gc($maxlifetime) {
  36.         global $db;
  37.  
  38.         $query = $db->query("DELETE FROM sessions WHERE UNIX_TIMESTAMP()-update>'$maxlifetime'",'SILENT');
  39.         if($db->affected_rows($query)) {
  40.                 return TRUE;
  41.         }
  42.         return FALSE;
  43. }
  44.  
  45. session_module_name();
  46. session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');
  47. session_start();
  48. ?>

在这个程序中,使用了Discuz!的db_mysql类,包含此程序前要打开数据库,主程序退出前不能关闭数据库,否则会出错。

还有一种保存会话的方法,效率较这种方法更高,那就是使用HEAP表,因为HEAP是将数据保存在内存里,节约内存就成了数据库设计的关键,如上面程序那样使用Text保存数据就不现实了,而且HEAP也不支持TEXT类型,Discuz!的session会话机制值得学习,它是按照自己所需要的字段,定制了表的内容,并且不依赖PHP自身的session.

4 Responses to “PHP:使用MySQL保存SESSION会话”

  1. bittercookie Says:

    前一段时间我看了resin里面的session的jdbcStore实现和sessionManager,和你上面这段代码原理相似,相比多加了些cache session的代码。原本是想实现单点登录的,后来发现不更改resin源代码竟然没有简单的办法实现这个功能。超级郁闷

  2. 孙小二 Says:

    博主可能是考虑如果一个目录下session文件过多,造成读写session的缓慢,如果单从这个角度考虑,可以按照一定规则分目录存放,php.ini中有相关配置,建议参考

  3. 孙小二 Says:

    至于分布式系统,nfs和其他文件同步工具也能很好解决这些问题,不过mysql这种方式可以解决垮域验证问题

  4. xjb Says:

    解决不了垮域问题,因为垮域是cookie要垮域(传递SID的方法除外)。

Leave a Reply