PHP SESSION入库 防止因SESSION写入不足而致服务器挂掉

一、为什么要SESSION入库

SESSION默认的存储媒介是文件,php.ini中的session.sava.handler选项。当SESSION文件较多时,通过文件系统的操作SESSION数据,会产生访问速度瓶颈问题。

SESSION数据会被系统序列化存储在SESSION会话文件中: C:\Windows\Temp

通过改写SESSION的存储机制,将SESSION存储在数据库中(MYSQL)或者Memcached、Redis等缓存服务器中,便于提升大量SESSION数据的操作效率,也便于SESSION数据共享。

本文主要讲解SESSION入库(MYSQL)。通过阅读,你可以:

  • 掌握SESSION自定义存储处理机制
  • 加深对SESSION存储机制的理解,加深SESSION、COOKIE区别联系的理解

二、SESSION存储管理机制

详细请参考 <<

接口说明参考 <<

PHP提供自定义会话存储处理器

方式1:
session_set_save_handler ( callable $open , callable $close , callable $read , callable $write , callable $destroy , callable $gc [, callable $create_sid [, callable $validate_sid [, callable $update_timestamp ]]] )
//需要先定义对应的回调函数(系统自行调用)
//调用session_set_sava_handler函数完成以上函数的注册
方式2:
session_set_save_handler(SessionHandlerInterface $handler,是否注册shutdown回调函数=true)
//$handler是SessionHandlerInterface接口实现类的对象

三、创建数据库

#创建数据库
create database db_session charest utf8;
#选择数据库
user db_session;

#创建数据表
create table tb_session(
    session_id varchar(100) primary key comment "会话内容",
    session_data text comment "session数据序列化字符串",
    session_time int not null default 0 comment "写入时间"
)charset =utf8 engine = innodb;

四、封装SESSION入库MYSQL

<?php
header("content-type:text/html;charset=utf8");
class MyHandler implements SessionHandlerInterface{
    private $handle = null;

    /**
     * [open 准备工作:数据库连接]
     * @param  [type] $save_path    [session文件的保存路径]
     * @param  [type] $session_name [COOKIE数据名(保存的是SESSION会话名称)]
     */
    public function open($save_path, $session_name)
    {
         $handle = mysql_connect('localhost','root','root') or die('数据库连接失败');     //连接MySQL数据库
         mysql_select_db('db_session',$handle) or die('数据库中没有此库名');     //找到数据库
         return(true);
    }
    /**
     * [read 按照会话名称,读取session数据]
     * @param  [type] $session_id [当前session会话的名称]
     * @return [type]             [session数据,从数据表中读取出来的序列化字符串]
     */
    public function read($session_id)
    {
        $time = time();         //设定当前时间   
        $sql = "select session_data from tb_session where session_id = '$session_id' and session_time > $time";
        $result = mysql_query($sql,$handle);
        $row = mysql_fetch_array($result);
        mysql_free_result($result); //释放结果集
        if ($row){
            return($row['session_data']);          //返回Session名称及内容
        }else{
            return(false);
        }
    }
    /**
     * [close 收尾工作,断开连接]
     * @return [type] [description]
     */
    public function close()
    {
        mysql_close($handle);
        return(true);
    }
    /**
     * [write 按照session_id将数据写入数据表]
     * @param  [type] $session_id   [当前会话名称]
     * @param  [type] $session_data [序列化后的session数据]
     */
    public function write($session_id,$session_data)
    {
        $time = 60*60;   //设置失效时间
        $lapse_time = time() + $time; //得到UNIX时间戳
        //如果会话存在 --更新操作
        //会话不存在 --写入操作
        //replace into --避免主键冲突
        $sql = "replace into tb_session values ('$session_id','$session_data',$time);";
        $result = mysql_query($sql,$handle);
        return($result);
    }
    /**
     * [destroy 销毁数据]
     * @param  [type] $session_id [销毁的会话数据对应的会话名称]
     */
    public function destroy($session_id)
    {
        $sql = "delete from tb_session where session_id = '$session_id'";            //删除数据库sql语句
        $result = mysql_query($sql,$handle);
        return($result);
    }
    /**
     * [gc 删除垃圾数据]
     * @param  [type] $expiry_time [垃圾回收机制中设定的最大时间]
     */
    public function gc($expiry_time)
    {
        $lapse_time = time();						//将参数$expiry_time赋值为当前时间戳
        $sql = "delete from tb_session where expiry_time < $lapse_time";  //删除数据库sql语句
        $result = mysql_query($sql,$handle);
        return($result);
    }
}
//直接传递函数名
//如果该函数参数个数较少,可以使用匿名函数
//session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
session_set_save_handler(new MyHandler, true);
/*// 开启SESSION会话 做准备工作
session_start();
$_SESSION['a']=1;
$_SESSION['b']='test_string';
*/
?>

五、FAQ

  • 同一IP不同浏览器的SESSION不同?
    • SESSION是基于浏览器的(SESSION是依赖于COOKIE)。每次浏览器请求时,系统安装浏览器版本信息,生成唯一的会话名称。不同浏览器请求,对应不同会话名称。
  • open回调函数的传递的session_name意义?
    • 用户请求时,浏览器会携带本网站的COOKIE数据给服务器脚本。session_name的值一般为PHPSESSID(可以在php.ini中的session.name进行设置)。
    • PHP按照PHPSESSID读取对应的COOKIE数据,如果有,则就是本次会话的session_id。如果没有则自动创建新的session_id。
  • 修改SESSION的保存时间,使其过期,下次访问SESSION数据一定会被清除吗?
    • 不一定。SESSION的GC垃圾回收机制,是在SESSION初始化时,按照一定的概率进行启动。由PHP.ini中session.gc_probability/sessiongc_divisor计算出启动的概率。只有在垃圾回收机制被启动,才能回收过期数据。大型网站,概率应该设置适当的小,避免性能消耗。

猜你喜欢

转载自blog.csdn.net/deaidai/article/details/79900285