SQL Relay

你是不是也在寻找LAMP结构下的PHP连接池?如果没找到更好的,建议你试试SQL Relay.
之前我曾将写过一篇关于SQL Relay的blog,介绍了一下怎么把SQL Realy用在PEAR DB中。事实证明,这样使用并不能有效的缓解MySQL中产生大量连接的问题,因为PHP从SQL Relay得到的还是一个真实的数据库连接,也就是说PHP连接一次,SQL Relay就要提供一个,至于这个连接什么时候还给SQL Relay,还是PHP说了算,SQL Relay没有管理权,所以运行了一段时间之后SQL Relay就会一下子增加N个连接,然后崩溃。。。。。。希望你没碰到这种状况。
最近实验了一下用另外一种方式使用SQL Relay,首先建立一个SQL Relay服务器,直接连接数据库,然后PHP端只建立到SQL Relay服务器的TCP连接,并不参与对数据库连接的使用和管理,基本的原理就是PHP连接到SQL Relay服务器,传递要运行的SQL语句,SQL Relay负责把语句通过一个空闲的连接送到MySQL服务器去执行得到结果后立即断开,然后返回给PHP,这样大量的PHP请求传递给SQL Relay,后者负责去维护一个MySQL连接池,完全拥有对数据库连接的管理权。经过实验,效果比较理想。
安装和配置运行这里就不赘述了,有问题可以mail我,说一下怎么实现PHP到SQL Relay的连接。
安装成功之后,在php.ini里设置sqlrelay.so的extension信息,然后可以按照下面的方法写一个class,你可以按照getRow方法的样子去实现其他的查询方法。

class SQLR_DB
{
private $conn;
private $cur;
private function __contruct(){}//构造函数
private function _conn($server,$port,$user,$password,$retrytime,$tries)//建立连接的私有方法(server:SQL Relay的服务器
,port:端口,user:用户名,password:密码,retrytime:隔多长时间重新连接,tries:重新连接的次数)
{
$this -> conn = sqlrcon_alloc($server,$port,"",$user,$password,$retrytime,$tries);
$this -> cur = sqlrcur_alloc($this->conn);
}

private function retrieve($sql) //传递SQL语句到SQL Relay服务器,获得返回结果的方法
{
if( !$sql) return false;
$this -> _conn("server" , "port" , "user" , "password" , "retrytime", "tries"); if(!sqlrcur_sendQuery($this->cur,$sql))
{
echo sqlrcur_errorMessage($this->cur);
sqlrcur_free($this->cur); sqlrcon_free($this->conn);
return null; }
//sqlrcon_endSession($con); for($i=0; $i < sqlrcur_rowCount($this->cur); $i++)
{ $res[] = sqlrcur_getRowAssoc($this->cur,$i);
} sqlrcur_free($this->cur);
sqlrcon_free($this->conn); return $res; }


然后在数据层通过这个class来取得数据。例如:

function getOneRecord($sql)
{
if(!$sql) return false;
$sdb = new SQLR_DB();
return $sdb -> getRow($sql);
}
public function getRow($sql)//取一行的共有方法
{
if(!$sql) return false;
$res = $this -> retrieve($sql);
if("null" == $res) return null;
return $res[0];
}
}

现在的问题是,用这种方法来对付所有的读操作是可以的(用来管理所有的对Slave服务器的读操作),但是用来管理写操作的时候却遇到了问题,在向数据库中写入一条记录,并返回插入ID的时候,以前可以使用mysql_insert_id方法,可是用SQL Relay来管理数据库连接之后,每次查询都有可能使用不同的连接,因此执行完一条insert语句,再去执行mysql_insert_id的时候,使用的很可能已经不是之前的连接了,因此也就不能返回正确的结果。不知道有哪位大侠知道解决方法的,请不吝赐教,在下感激不尽:)

1 comment so far ↓

#1 kakapo on 05.04.08 at 2:03 pm

last_insert_id() 不会返回错误的Id,因为sqlrelay 是基于会话机制的,php每次连接上sqlrelay算一次会话,等到php脚本执行结束后会话才终止,那么只要在此会话只内,无论php执行多少句sql语句,sqlrelay始终用同一个连接来服务。

说吧。。。