優化使用mysql存儲session

日期:2008-07-05  作者:喜騰小二  來源:PHPChina


之前寫過兩篇文章《自定義SESSION(二)——數據庫保存》《我為什麼不使用session》
  但後來發現都有問題。前者處理在實際中幾乎沒什麼用處,而且session回收還得自己另外處理。後者頻繁的操作數據庫,打來了很大的性能問題。

  這兩天仔細考慮下,大緻給出一個方案,但還沒有俱體詳細的測試。
  1、session處理和統計結合起來。同時遊客也都有記錄。
  2、完全使用數據庫和cookie來模擬session的功能。
  3、用戶的對session的操作都盡量保證在一條sql語句完成。不用到session的時候,絕對不多一條查詢。
  4、為了效率起見,session的回收沒有集成進來,但提供了接口,可以調用實現。

暫時給出代碼,不俱體解釋。
sql


CREATE TABLE `*****_session` (
 `sid` char(32) NOT NULL,
 `uid` int(10) NOT NULL,
 `username` char(32) NOT NULL,
 `usertype` tinyint(1) NOT NULL,
 `activetime` int(10) NOT NULL,
 `expiry` int(10) NOT NULL,
 `ip` char(15) NOT NULL,
 `url` char(80) NOT NULL,
 `value` char(255) NOT NULL,
 PRIMARY KEY  (`sid`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;



php代碼

class session{
    
    private 
$_sessionPrex'';
//session的前綴
    
    
private $_time '';
//當前時間
    
    
private $_model null;
//數據庫操作模型
    
    
private $_expiry 1200;
//session有效時間
    
    
private $_domain '';
//session的作用域
    
    
protected $isNew 0;
//判定操作動作 0 更新 1 增加
    
    
protected $session = array();
//對應的一條session記錄
    
    
public function __construct($options
){
        
$this->_setOptions($options
);
        if(empty(
$this->_time))$this->_time time
();
        
$this->session['activetime'] = $this->_time
;
    }
    
    public function 
start
(){
        
$this->_getSid
();
    }
    
    public function 
set($key,$value
){
        if(
in_array($key,array('uid','username','usertype','url','expiry'
))){
            if(
$key == 'expiry'
){
                
$this->_setCookie($this->_sessionPrex.'_sid',$this->session['sid'],$value
);
                
$this->_setCookie($this->_sessionPrex.'_uid',$this->session['uid'],$value
);
            }
            
$this->session[$key] = $value
;
        }else{
            
$other $this->session['value'
];
            
$other[$key] = $value
;
            
$this->session['value'] = $other
;
        }
    }
    
    public function 
get($key
){
        if(
in_array($key,array('uid','username','usertype','url','expiry'
))){
            return 
$this->session[$key
];
        }else{
            if(isset(
$this->session['value'][$key
])){
                return 
$this->session['value'][$key
];
            }
            return 
null
;
        }
    }
    
    public function 
gc($file,$time 1200
){
        
$lasttime file_get_contents($file
);
        if(
$lasttime $time<$this->_time
){
            
file_put_contents($file,$this->_time
);
            return 
$this->_model->delete('activetime+expiry<'.$this->_time
);
        }
    }
    
    public function 
destroy
(){
        
$this->session['uid'] = 0
;
        
$this->session['username'] = ''
;
        
$this->session['usertype'] = -1
;
        
$this->session['expiry'] = $this->_expiry
;
        
$this->session['value'
] = array();
        
$this->_setCookie($this->_sessionPrex.'_sid',$this->session['sid'],$this->_expiry
);
        
$this->_setCookie($this->_sessionPrex.'_uid',$this->session['uid'],$this->_expiry
);
    }
    
    public function 
__destruct
(){
        
$this->_save
();
    }
    
    private function 
_save
(){
        
$dbSession $this->session
;
        
$dbSession['value'] = serialize($dbSession['value'
]);
        if(
strlen($dbSession['value'])>255)$this->_error('session->value is too long!'
);
        if(
$this->isNew == 1
){
            
//增加
            
$this->_model->insert($dbSession
);
        }else{
            
//更新
            
$sid $dbSession['sid'
];
            
$this->_model->update(array_slice($dbSession,1),'sid=''.$sid.'''
);
        }
    }
    
    private function 
_getSession($sid
){
        
$dbSession $this->_model->detail('sid = ''.$sid.'''
);
        if(!
$dbSession)return false
;
        
$dbSession['value'] = unserialize($dbSession['value'
]);
        
$this->session array_merge($dbSession,$this->session
);        
        return 
true
;
    }
    
    private function 
_getSid
(){
        
$sid strip_tags($_COOKIE[$this->_sessionPrex.'_sid'
]);
        if(
strlen($sid)==32
){
            if(
$this->_getSession($sid
)){
                return 
true
;
            }
        }else{
            
$sid md5(time().mt_rand(1000,10000
));
            
$this->_setCookie($this->_sessionPrex.'_sid',$sid
);
        }
        
$this->_setCookie($this->_sessionPrex.'_uid',0
);
        
$this->session 
= array(
                
'uid' => 0
,
                
'username' => ''
,
                
'usertype' => -1
,
                
'activetime' => $this->_time
,
                
'ip' => $this->_getip
(),
                
'url' => strip_tags($_SERVER['REQUEST_URI'
]),
                
'expiry' =>$this->_expiry
,
                
'value' 
=> array()
        );
        
$this->isNew 1
;
        
$this->session['sid'] = $sid
;
    }
    
    private function 
_setCookie($name,$value,$expiry=0
){
        if(empty(
$expiry))$expiry $this->_expiry
;
        if(empty(
$this->_domain
)){
            
setcookie($name,$value,$this->_time $expiry,'/'
);
        }else{
            
setcookie($name,$value,$this->_time $expiry,'/',$this->_domain
);
        }
    }
    
    private function 
_getip
(){
        return 
getip
();
    }
    
    private function 
_setOptions($options
){
        foreach (
$options as $key=>$value
){
            if(
in_array($key,array('sessionPrex','time','model','expiry','domain'
))){
                
$key '_'.$key
;
                
$this->$key $value
;
            }
        }
    }
    
    private function 
_error($msg
){
        throw new 
Phpbean_Exception($msg
);
    }
}
?>

(注意,該代碼不能直接使用,本文主要是提供一種思路)

<<<返回技術中心

技術文章

站內新聞

我要啦免费统计