優(yōu)化使用mysql存儲(chǔ)session的php代碼
更新時(shí)間:2008年01月10日 19:47:24 作者:
優(yōu)化使用mysql存儲(chǔ)session的php代碼
之前寫過兩篇文章《自定義SESSION(二)——數(shù)據(jù)庫保存》和《我為什么不使用session》
但后來發(fā)現(xiàn)都有問題。前者處理在實(shí)際中幾乎沒什么用處,而且session回收還得自己另外處理。后者頻繁的操作數(shù)據(jù)庫,打來了很大的性能問題。
這兩天仔細(xì)考慮下,大致給出一個(gè)方案,但還沒有具體詳細(xì)的測試。
1、session處理和統(tǒng)計(jì)結(jié)合起來。同時(shí)游客也都有記錄。
2、完全使用數(shù)據(jù)庫和cookie來模擬session的功能。
3、用戶的對(duì)session的操作都盡量保證在一條sql語句完成。不用到session的時(shí)候,絕對(duì)不多一條查詢。
4、為了效率起見,session的回收沒有集成進(jìn)來,但提供了接口,可以調(diào)用實(shí)現(xiàn)。
暫時(shí)給出代碼,不具體解釋。
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 = '';//當(dāng)前時(shí)間
private $_model = null;//數(shù)據(jù)庫操作模型
private $_expiry = 1200;//session有效時(shí)間
private $_domain = '';//session的作用域
protected $isNew = 0;//判定操作動(dòng)作 0 更新 1 增加
protected $session = array();//對(duì)應(yīng)的一條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);
}
}
?>
(注意,該代碼不能直接使用,本文主要是提供一種思路)
但后來發(fā)現(xiàn)都有問題。前者處理在實(shí)際中幾乎沒什么用處,而且session回收還得自己另外處理。后者頻繁的操作數(shù)據(jù)庫,打來了很大的性能問題。
這兩天仔細(xì)考慮下,大致給出一個(gè)方案,但還沒有具體詳細(xì)的測試。
1、session處理和統(tǒng)計(jì)結(jié)合起來。同時(shí)游客也都有記錄。
2、完全使用數(shù)據(jù)庫和cookie來模擬session的功能。
3、用戶的對(duì)session的操作都盡量保證在一條sql語句完成。不用到session的時(shí)候,絕對(duì)不多一條查詢。
4、為了效率起見,session的回收沒有集成進(jìn)來,但提供了接口,可以調(diào)用實(shí)現(xiàn)。
暫時(shí)給出代碼,不具體解釋。
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 = '';//當(dāng)前時(shí)間
private $_model = null;//數(shù)據(jù)庫操作模型
private $_expiry = 1200;//session有效時(shí)間
private $_domain = '';//session的作用域
protected $isNew = 0;//判定操作動(dòng)作 0 更新 1 增加
protected $session = array();//對(duì)應(yīng)的一條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);
}
}
?>
(注意,該代碼不能直接使用,本文主要是提供一種思路)
您可能感興趣的文章:
- 發(fā)款php蜘蛛統(tǒng)計(jì)插件只要有mysql就可用
- PHP使用redis實(shí)現(xiàn)統(tǒng)計(jì)緩存mysql壓力的方法
- PHP+Mysql+jQuery中國地圖區(qū)域數(shù)據(jù)統(tǒng)計(jì)實(shí)例講解
- PHP+Mysql+jQuery文件下載次數(shù)統(tǒng)計(jì)實(shí)例講解
- PHP+MySQL統(tǒng)計(jì)該庫中每個(gè)表的記錄數(shù)并按遞減順序排列的方法
- php 廣告點(diǎn)擊統(tǒng)計(jì)代碼(php+mysql)
- php下MYSQL limit的優(yōu)化
- php導(dǎo)入大量數(shù)據(jù)到mysql性能優(yōu)化技巧
- php+mysql查詢優(yōu)化簡單實(shí)例
- PHP數(shù)據(jù)庫編程之MySQL優(yōu)化策略概述
- PHP+MySQL實(shí)現(xiàn)對(duì)一段時(shí)間內(nèi)每天數(shù)據(jù)統(tǒng)計(jì)優(yōu)化操作實(shí)例
相關(guān)文章
fleaphp rolesNameField bug解決方法
fleaphp rolesNameField bug解決方法,需要的朋友可以參考下。2011-04-04解決wincache不支持64位PHP5.5/5.6的問題(提供64位wincache下載)
這篇文章主要解決wincache不支持64位PHP5.5/5.6的問題,并提供64位wincache的下載,需要的朋友可以參考下。2016-06-06常用的PHP數(shù)據(jù)庫操作方法(MYSQL版)
最近一直在折騰自己的網(wǎng)站首頁,寫的大部分PHP腳本都要用到和MYSQL數(shù)據(jù)庫相關(guān)的操作,今天把這些方法和大家分享一下,希望大家能多多交流!2011-06-06PHP取得一個(gè)類的屬性和方法的實(shí)現(xiàn)代碼
PHP取得一個(gè)類的屬性和方法的實(shí)現(xiàn)代碼,需要的朋友可以參考下。2011-05-05PHP setcookie指定domain參數(shù)后,在IE下設(shè)置cookie失效的解決方法
setcookie函數(shù)指定domain參數(shù)后,在IE下的表現(xiàn)和在chrome、firefox中的表現(xiàn)不同,這不是php setcookie函數(shù)的問題,這是IE的問題。2011-09-09PHP實(shí)現(xiàn)抓取迅雷VIP賬號(hào)的方法
這篇文章主要介紹了PHP實(shí)現(xiàn)抓取迅雷VIP賬號(hào)的方法,實(shí)例分析了php基于采集類Snoopy實(shí)現(xiàn)頁面抓取及正則匹配的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07