关于多数据库的问题

#1 小柒

根据这个帖子http://www.speedphp.com/thread-3794-1-1.html ,我重新写了spModelNew的类,然后其他model继承spModelNew,我用的是mysql,在这个类的构造函数中,
public function __construct(){
                if( null == $this->tbl_name )$this->tbl_name = $GLOBALS['G_SP']['db']['prefix'] . $this->table;
               
                // 从库(读取库)实例化驱动
                $this->_db_read = spClass('db_mysql', array($this->db_slave), SP_PATH.'/Drivers/mysql.php',true);
     // 主库(写入库)实例化驱动
                $this->_db_write = spClass('db_mysql', array($this->db_master), SP_PATH.'/Drivers/mysql.php', true);
        }

分别实例化了  $this->_db_read , $this->_db_write ,但是经过程序的调试发现,实际上连接的只有一个数据库,就是 $this->_db_write 的连接句柄, 调用model的find方法时,和create的方法时, $this->_db_read , $this->_db_write 是一个数据库句柄,是因为spClass的原因吗,spClass()在实例化对象前将检查该类是否已经实例化,如发现类已实例化,将直接返回该类的对象句柄,以节省资源。难道是因为这样导致的?还是我的写法有误?
如果可以的话,麻烦jake帮我看看这个问题,是不是我要用new才能避免这个问题

2013-06-29 20:34:23

#2 jake

spClass是带单例效果的,也就是一直只有一个对象。但是第四个参数可以控制这个行为,看帖子里面的spClass的参数吧。

2013-06-30 00:04:20

#3 小柒

我设置的是true,但是连个连接对象用dump调试出来看,它们的[conn] => Resource id 14
都是一样的 ,连个连的都是一个数据库?

2013-06-30 15:32:24

#4 jake

先上代码:
        $dsn_1 = spClass('db_mysql', array(array(
            'host' => 'localhost',
            'login' => 'root',
            'password' => '',
            'database' => 'one',
        )), SP_PATH.'/Drivers/mysql.php', TRUE);

        $dsn_2 = spClass('db_mysql', array(array(
            'host' => 'localhost',
            'login' => 'root',
            'password' => '',
            'database' => 'test',
        )), SP_PATH.'/Drivers/mysql.php', TRUE);

        var_dump($dsn_1);
        echo "

";
        var_dump($dsn_2);
这里会有些误会,估计你测试的使用是用同一个地址吧。
实际上PHP一次运行期间,连接同一个数据库地址(地址参数用户名什么都相同的情况下)["conn"]=> resource(12) of type (mysql link),Resources都是只有一个,这是PHP节省资源的做法吧。如上代码,就会有:
object(db_mysql)5 (2) { ["conn"]=> resource(12) of type (mysql link) ["arrSql"]=> array(1) { [0]=> string(14) "SET NAMES UTF8" } } 

object(db_mysql)6 (2) { ["conn"]=> resource(12) of type (mysql link) ["arrSql"]=> array(1) { [0]=> string(14) "SET NAMES UTF8" } }
除非连接地址参数不一样,举例,这里是一个localhost和一个127.0.0.1,虽然是同一个数据库,但是参数不同。
        $dsn_1 = spClass('db_mysql', array(array(
            'host' => 'localhost',
            'login' => 'root',
            'password' => '',
            'database' => 'one',
        )), SP_PATH.'/Drivers/mysql.php', TRUE);

        $dsn_2 = spClass('db_mysql', array(array(
            'host' => '127.0.0.1',
            'login' => 'root',
            'password' => '',
            'database' => 'test',
        )), SP_PATH.'/Drivers/mysql.php', TRUE);

        var_dump($dsn_1);
        echo "

";
        var_dump($dsn_2);
结果是:(有时候要刷新多几次,因为页面有缓存,资源也有缓存)
object(db_mysql)5 (2) { ["conn"]=> resource(12) of type (mysql link) ["arrSql"]=> array(1) { [0]=> string(14) "SET NAMES UTF8" } } 

object(db_mysql)6 (2) { ["conn"]=> resource(13) of type (mysql link) ["arrSql"]=> array(1) { [0]=> string(14) "SET NAMES UTF8" } }
可以看到Resouces就不同了,
["conn"]=> resource(12) of type (mysql link)
["conn"]=> resource(13) of type (mysql link)

也就是当你用真正不同的两个连接地址(比如说两个不同的主从库的IP时),就会有读写分离的效果了。

另外,spClass第四个参数为true,指的是db_mysql这个类实例化后的对象是不同的。object(db_mysql)5和object(db_mysql)6,但是不代表他们的成员变量conn是不同的。conn是连接资源,上面已经说过怎么样会连接两个资源了(参数相同情况只连接一个)

2013-06-30 18:26:33