一般情况下,php.ini里的session.save_handler默认是file,也就是用文件来保存session,这种方式有几个缺点:

1、如果单靠session自己的垃圾回收机制,时间久了,保存session的文件会越来越多,影响查找效率;

2、对于需要统计同时在线用户的系统,实现起来很不方便;

3、分布式系统难以共享session。



如果将session.save_handler设置为user,php可以通过session_set_save_handler函数来重载session的几个底层会话处理方法,以达到使用数据库来保存session的目的,下面以mysql数据库为例,数据库连接方式采用PDO。

session.sql

  1. CREATE TABLE `session` (
  2. `session_id` varchar(32) NOT NULL default '',
  3. `session_content` text NOT NULL,
  4. `last_visit` int(11) NOT NULL,
  5. PRIMARY KEY (`session_id`)
  6. ) ENGINE=MyISAM;

此处建议使用ENGINE=MEMORY,MEMORY引擎采用内存表,所有数据存储在内存,操作速度快,对于session这种形式的数据正好适用。

session.php

  1. <?PHP
  2. // --------------------------------------------------------------------------
  3. // File name : session.php
  4. // Description : 数据库存放session
  5. // Copyright(C), MagicLab.cn, 2008, All Rights Reserved.
  6. // Author: xinglu QQ:330708730 MSN:xinglu_1983@hotmail.com
  7. // --------------------------------------------------------------------------
  8. class Session {
  9. var $lifeTime;
  10. var $domain;
  11. var $dbh;
  12. function __construct()
  13. {
  14. //定义生存期
  15. $this->lifeTime = 3600;
  16. //定义域
  17. $this->domain = $_SERVER['SERVER_NAME'];
  18. try
  19. {
  20. $this->dbh = new PDO('mysql:host=localhost;dbname=session', 'root', '');
  21. $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
  22. //PDO出错方式 跑出异常
  23. $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  24. }
  25. catch (PDOException $e)
  26. {
  27. throw $e;
  28. }
  29.  
  30. //设置session生存期
  31. ini_set('session.gc_maxlifetime', $this->lifeTime);
  32.  
  33. //设置客户端使用COOKIE保存SESSIONID
  34. ini_set('session.use_cookies', 1);
  35. ini_set('session.cookie_path', '/');
  36.  
  37. //多主机共享保存SESSIONID的COOKIE(使二级域名可以共享session)
  38. ini_set('session.cookie_domain', $this->domain);
  39.  
  40. //设置客户端保存 SESSIONID 的cookie的生存期
  41. ini_set('session.cookie_lifetime', $this->lifeTime);
  42.  
  43. //为保持客户端cookie生命期与服务端session生命期相同,进行写cookie操作
  44. $sessionid = session_id();
  45. $sessionname = session_name();
  46. setcookie($sessionname, $sessionid, $this->lifeTime, '/', $this->domain);
  47.  
  48. //将session.save_handler设置为user,而不是默认的 files
  49. session_module_name('user');
  50.  
  51. //重载session函数
  52. session_set_save_handler(array(&$this,"open"),
  53. array(&$this,"close"),
  54. array(&$this,"read"),
  55. array(&$this,"write"),
  56. array(&$this,"destroy"),
  57. array(&$this,"gc")
  58. );
  59.  
  60. }
  61.  
  62. function open($savePath, $sessName)
  63. {
  64. $this->gc();
  65. return true;
  66. }
  67.  
  68. function close()
  69. {
  70. $this->gc();
  71. unset($this->dbh);
  72. return true;
  73. }
  74.  
  75. function read($session_id)
  76. {
  77. if (!isset($session_id))
  78. return "";
  79.  
  80. $last = time() - $this->lifeTime;
  81.  
  82. $sql = sprintf("SELECT session_content
  83. FROM session
  84. WHERE session_id = '%s'
  85. AND last_visit > ".$last
  86. ,$session_id);
  87. try
  88. {
  89. $query = $this->dbh->query($sql);
  90. if($row = $query->fetch(PDO::FETCH_ASSOC))
  91. return $row['session_content'];
  92. }
  93. catch(PDOException $e)
  94. {
  95. echo $e->getMessage();
  96. die();
  97. }
  98. return "";
  99. }
  100.  
  101. function write($session_id, $session_content)
  102. {
  103. if (!isset($session_id))
  104. return "";
  105.  
  106. $sql = sprintf("SELECT * FROM session WHERE session_id='%s'", $session_id);
  107.  
  108. try
  109. {
  110. $sth = $this->dbh->query($sql);
  111. $rs = $sth->fetchAll(PDO::FETCH_ASSOC);
  112. if (is_array($rs) && !empty($rs))
  113. {
  114. $sql = sprintf("UPDATE session
  115. SET session_content='%s',last_visit=%d
  116. WHERE session_id='%s';"
  117. ,$session_content
  118. ,time()
  119. ,$session_id
  120. );
  121. }
  122. else
  123. {
  124. $sql = sprintf("INSERT INTO session
  125. SET session_id='%s',session_content='%s',last_visit=%d;"
  126. ,$session_id
  127. ,$session_content
  128. ,time()
  129. );
  130. }
  131.  
  132. $rs = $this->dbh->exec($sql);
  133. if($rs)
  134. return true;
  135. }
  136. catch(PDOException $e)
  137. {
  138. echo $e->getMessage();
  139. die();
  140. }
  141. return false;
  142. }
  143.  
  144. function destroy($session_id)
  145. {
  146. if (!isset($session_id))
  147. return true;
  148.  
  149. $sql = sprintf("DELETE FROM session WHERE session_id = '%s'", $session_id);
  150. try
  151. {
  152. $rs = $this->dbh->exec($sql);
  153. if($rs)
  154. return true;
  155. }
  156. catch(PDOException $e)
  157. {
  158. echo $e->getMessage();
  159. die();
  160. }
  161. return false;
  162. }
  163.  
  164. function gc()
  165. {
  166. $last = time() - $this->lifeTime;
  167. $sql = sprintf("DELETE FROM session WHERE last_visit < ".$last);
  168. $sth = $this->dbh->exec($sql);
  169. return $sth;
  170. }
  171. }
  172.  
  173. ?>

使用方法:

test.php

  1. <?php
  2. require_once('session.php');
  3. $session = new Session;
  4. session_start();
  5. ?>

类文件里有一个有些特别的地方:

//为保持客户端cookie生命期与服务端session生命期相同,进行写cookie操作  

$sessionid = session_id();  

$sessionname = session_name();  

setcookie($sessionname, $sessionid, $this->lifeTime, '/', $this->domain);

如果只是单单将session.gc_maxlifetime和session.cookie_lifetime的设置成相同的时间,那么以后在每次session_start()的时候,服务端session的生存期都会自动得到延长,但是保存sessionid的cookie却没有。当然,也可以直接将session.cookie_lifetime设置成一个非常大的数,只是这样显得比较霸道。

数据库保存session的更多相关文章

  1. 如何使用数据库保存session的方法简介

    使用数据库保存session的方法 php的session默认是以文件方式保存在服务器端,并且在客户端使用cookie保存变量,这就会出现一个问题,当一个用户由于某种安全原因关闭了浏览器的cookie ...

  2. [转]PHP用mysql数据库存储session

    From : http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2010/0226/4002.html 大部分使用php的人一旦应用到sessio ...

  3. Asp.Net保存session的三种方法 (Dll文件更新导致session丢失的解决办法)

    1. InProc模式(默认值):asp.net将session保存到当前进程中,这种方式最快,但是不能多台服务器共享session,且会话状态数据容易丢失. <sessionState mod ...

  4. PHP用mysql数据库存储session

    大部分使用php的人一旦应用到session都会使用cookie. cookie虽好可是它也会给我们带来一些隐患的. 隐患一:如果客户端机器的cookie一旦因病毒而失效了,那么session也就相当 ...

  5. Asp.Net 保存Session的三种方式

    一.默认方式,保存在IIS进程中保存在IIS进程中是指把Session数据保存在IIS的运行的进程中,也就是inetinfo.exe这个进程中,这也是默认的Session的存方式,也是最常用的. 这种 ...

  6. 使用aspnet_regsql.exe 创建ASPState数据库,用来保存session会话

    使用aspnet_regsql.exe 创建ASPState数据库,用来保存session会话   因为公司有多台服务器,所以session要保存在sql server上,因此要在数据库中建立存放se ...

  7. laravel中将session由文件保存改为数据库保存

    1.laravel中默认是使用文件保存session的,保存在/storage/framework/sessions下 2.修改配置文件 config/session.php中 'driver' =& ...

  8. redis/分布式文件存储系统/数据库 存储session,解决负载均衡集群中session不一致问题

    先来说下session和cookie的异同 session和cookie不仅仅是一个存放在服务器端,一个存放在客户端那么笼统 session虽然存放在服务器端,但是也需要和客户端相互匹配,试想一个浏览 ...

  9. Asp.Net保存session的三种方法

    C#中保存Session的三种方法及Web.Config设置 1.保存session到sql server,需要指定Sql Server服务器,这种方法因为要读写数据库最慢 <sessionSt ...

随机推荐

  1. 打开Word 2010 老提示安装 Office single image 2010

    解决办法: WScript.Echo "Try to repair registry key..."  'verify Office version  Set objshell = ...

  2. tomcat 安装与使用!

    $安装:安装方式为zip解压. 打开tomcat官网点此链接:https://tomcat.apache.org/download-80.cgi 选择你想要使用的版本,点击相应位数选择zip解压包版, ...

  3. js实现深拷贝

    type函数 首先我们要实现一个getType函数对元素进行类型判断,直接调用Object.prototype.toString 方法. function getType(obj){ //tostri ...

  4. 转载:解决CentOS7虚拟机无法上网并设置CentOS7虚拟机使用静态IP上网

    最近在VMware虚拟机里玩Centos,装好后发现上不了网.经过一番艰辛的折腾,终于找到出解决问题的方法了.最终的效果是无论是ping内网IP还是ping外网ip,都能正常ping通.方法四步走: ...

  5. ecliplse的下载安装

    ecliplse的官方下载地址是: https://www.eclipse.org/downloads/packages/ 进去的速度可能比较慢,请耐心等待,进去之后的页面如下,为了便于理解下面的是我 ...

  6. iOS 开发之 GCD 不同场景使用

    header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...

  7. Java面向对象之构造代码块 入门实例

    一.基础概念 1.构造代码块,给所有对象进行初始化. 2.构造函数,只给对应的对象初始化. 3.局部代码块,控制局部变量的生命周期. 二.实例代码 class Person { private int ...

  8. #首行输入数n,接下来输入n行数,以空格隔开

    #首行输入数n,接下来输入n行数,以空格隔开 n = int(raw_input())# print nL = []for i in range(n): L.append([int(x) for x ...

  9. Docker - CentOS 安装 Docker 和 Docker-Compose

    目录 介绍 Docker Docker-Conpose 安装 Docker CE 系统要求 使用 YUM 安装 配置加速器 安装 Docker-Compose 介绍 Docker Docker 是一个 ...

  10. 3C - Youmu

    (ans & arr[j]) == ans 保证高位已有值不失效. ((ans[j] >> (i - 1)) & 1) == 1 当前位为1,cnt++, cnt > ...