在单个脚本中连接多个数据库的优缺点

Pros and cons of connecting more than one database in single script

假设用户在单个主机上托管了两个数据库,我需要连接到这两个数据库,这样我就可以随时使用任何 table 而无需多次添加连接代码。

我在 CodeIgniter 中实现了这个,在 database.php 文件中添加了两个数据库的授权细节,并在脚本中使用 $this->load->database('dbname'); 加载所需的数据库。

现在,对于核心 PHP,我们可以这样做:

mysql_connect ('host','user','password','port','dbname'); // connection with one database.   

它连接了我的第一个数据库。

现在,我想连接第二个数据库:

1) 我还没有关闭上面的连接并用

连接到第二个
mysql_connect ('host','user','password','port','dbname1');.

2) 这样做是不好的做法吗?它会消耗更多的对象吗?无论如何我们都应该关闭第一个吗?

1) Is it possible to connect with more than one database in one script ?

是的,我们可以在同一脚本中创建多个 MySQL link 标识符。

2) It should be not like to close one connection with mysql_close and open new one,rather both connection should open at a time and user can use any table from any of the database ?

像mysql_pconnect

一样使用持久数据库连接

3) If it is possible,what can be disadvantage of this ? Will there create two object and this will going to create issue ?

除了增加服务器负载外,我不认为它会造成任何问题。

你可以这样使用

$db1 = mysql_connect($hostname, $username, $password); 
$db2 = mysql_connect($hostname, $username, $password, true); 

mysql_select_db('abc', $db1);
mysql_select_db('def', $db2);

对于数据库 1

mysql_query('select * from table1', $db1);

对于数据库 2

mysql_query('select * from table2', $db2);

你试过吗?

$mysqli1 = new mysqli("example.com", "user", "password", "database1");

$mysqli2 = new mysqli("example.com", "user", "password", "database2");

如果mysql的用户有两个数据库的权限,你可以从两个数据库加入两个table 等:

SELECT database1.table.title title1,database2.table.title title2 
FROM database1.table
INNER JOIN database2.table 
ON (database1.table.id=database2.table.id)

Q: What cons are there to connect with other database without closing previous database?

A:当您连接到数据库服务器时,物理上正在分配资源以与您交互,如果两个数据库在同一台服务器上,您将不必要地使用可用于处理其他连接或其他活动的资源。因此,您将关闭不需要继续使用的连接。

Q: Is this a appropriate practice to do so ? What is the best way to do so without opening this connection in every script multiple times ? I want this to get done in core php only as I have already know this in codeigniter.

SESSIONS 的一种方式,但您不能在会话中存储数据库连接。阅读 PHP.net 这个警告:"Some types of data can not be serialized thus stored in sessions. It includes resource variables or objects with circular references (i.e. objects which passes a reference to itself to another object)." MySQL 连接就是这样一种资源。

您必须在每个页面上重新连接 运行。

如果您可以通过 mysql_pconnect() 依赖连接池,这并没有听起来那么糟糕。连接时,该函数将首先尝试查找已经使用相同主机、用户名和密码打开的(持久)link。如果找到,将返回它的标识符而不是打开新连接。当脚本执行结束时,与 SQL 服务器的连接不会关闭。相反,link 将保持开放以供将来使用(mysql_close() 不会关闭由 mysql_pconnect() 建立的 link)。

参考:

http://php.net/manual/en/function.mysql-pconnect.php

http://www.php.net/manual/en/intro.session.php

Can't pass mysqli connection in session in php

使用多个数据库的最佳方式是使用PDO函数

例子

// database cobfigurations
$config= array(
    // first database
    array(
        'type'=>'mysql',                    // DB type
        'host'=>'localhost',                // DB host
        'dbname'=>'database1',      // DB name
        'user'=>'root',                 // DB username
        'pass'=>'12345',                // DB password
    ),
    // second database
    array(
        'type'=>'mysql',                    // DB type
        'host'=>'localhost',                // DB host
        'dbname'=>'database2',      // DB name
        'user'=>'root',                 // DB username
        'pass'=>'987654',               // DB password
    ),
);
// database connections
$mysql=array();
foreach($config as $con)
{
    $con=(object)$con;
    $start= new PDO($con->type.':host='.$con->host.';dbname='.$con->dbname.'', $con->user, $con->pass, array(
            // pdo setup
            PDO::ATTR_PERSISTENT            => FALSE,
            PDO::ATTR_DEFAULT_FETCH_MODE    => PDO::FETCH_OBJ,
            PDO::ATTR_ERRMODE               => PDO::ERRMODE_EXCEPTION,
            PDO::MYSQL_ATTR_INIT_COMMAND    => 'SET NAMES UTF8'
    ));

    if ($start && !empty($start) && !is_resource($start))
        $mysql[]=$start;    // connection is OK prepare objects
    else
        $mysql[]=false; // connection is NOT OK, return false
}

/**********************
 ****  HOW TO USE ****
**********************/ 

// fetch data from database 1
$data1 = $mysql[0]->query("SELECT id, title, text FROM content1")->fetchAll();
if(count($data1)>0)
{
    foreach($data1 as $i=>$result)
    {
        echo $result->id.' '.$result->title.' '.$result->text.'<br>'
    }
}

// fetch data from database 2
$data2 = $mysql[1]->query("SELECT id, title, text FROM content2")->fetchAll();
if(count($data2)>0)
{
    foreach($data2 as $i=>$result)
    {
        echo $result->id.' '.$result->title.' '.$result->text.'<br>'
    }
}

如果您以前没有使用过 PDO,请阅读这个简短的教程:

http://www.mysqltutorial.org/php-querying-data-from-mysql-table/

实际上与 mysql 和 mysqli 连接相同,但更先进、快速和安全。

阅读此文档: http://php.net/manual/en/book.pdo.php

您还可以添加 2 个以上的数据库

您可以通过遵循面向对象的方法来做到这一点

首先创建与两个数据库的连接:

$Db1 = new mysqli('localhost','root','','database1'); // this is object of database 1
$Db2 = new mysqli('localhost','root','','database2'); // this is object of database 2

$query1 = 'select * from `table_name_of_database1`';  // Query to be run on DB1
$query2 = 'select * from `table_name_of_database2`';   // Query to be run on DB2

$result1 = $Db1->query($query1); // Executing query on database1 by using $Db1
$result2 = $Db2->query($query2); // Executing query on database2 by using $Db2

echo "<pre>";

/* Print result of $query1 */

if ($result1->num_rows > 0) {
    while($row = $result1->fetch_assoc()) {
        print_r($row);
    }
} else {
    echo "0 results";
}


/*========================================================*/


/* Print result of $query2 */

if ($result2->num_rows > 0) {
    while($row = $result2->fetch_assoc()) {
         print_r($row);
    }
} else {
    echo "0 results";
}

结论:当你想使用database1时使用$Db1对象,如果你想使用database2则使用$DB2.

我不认为如何同时连接到 2 个数据库是问题,因为您已经成功地做到了(或知道如何做到)。我可以从你的问题中收集到这一点。所以我不会展示如何做到这一点。如果需要,请参阅其他答案。

但要直接解决您的问题:

  1. 这样做是不好的做法吗?通常,应尽可能避免同时处理 2 个 DB 连接句柄。如果您只需要从一个数据库中获取数据并使用它们在另一个数据库中执行某些操作,那么最好的办法是将来自 DB1 的数据放入适当的 PHP 变量中,关闭连接;然后进行第二次连接。这比同时保持 2 个数据库连接打开要便宜。但是,如果您正在做类似 INSERT INTO db1.table SELECT FROM db2.table 并且还需要根据某些查询的成功或失败来提交或回滚,那么 AFAIK,您需要同时保留两者连接打开,直到您的流程结束。你看,总是有取舍。所以您根据您的应用需求来决定并承担费用。

作为这种情况的一个实际例子,我曾经在一个项目中工作,我需要 SELECT 一个 table1,INSERT INTO 一个 table2,如果 INSERT 成功,我删除 table1 中的所有行,如果DELETE 失败,我回滚 INSERT 操作,因为数据不能同时存在于两个表中。

当然,我自己的案例只涉及一个DB,所以不需要二次连接。但是假设这两个表在不同的数据库上,那么这可能与您的情况相似。

  1. 会消耗更多的对象吗?除了上面1中指出的对象外,没有其他对象,即根据您的问题处理的DB连接。

  2. 我们是否应该强制要求关闭第一个?再次强调,取决于您的应用需求。

不需要为了使用同一台服务器上的2个数据库中的表而打开2个连接。您只需要使用 database.table 表示法。这样做意味着您甚至可以在同一查询中连接来自不同数据库的表

SELECT t1.col1, t1.col2, t2.col2, t2.col2
FROM db1.table1 AS t1 JOIN db2.table1 AS t2 ON t1.col1 = t2.col3

因此,如果您最初连接到 db1,则可以使用 db2 表,同样,如果您连接到 db2,则可以使用 db1 表。

而不是 mysql_connect 使用 mysqli_connect.

mysqli 提供一次连接多个数据库的功能。

这是一个简单的class,可以在需要时自动选择所需的数据库。

class Database 
{
    private $host   = 'host';
    private $user   = 'root';
    private $pass   = 'pass';
    private $dbname = '';

    private $mysqli = null;

    function __construct() 
    {
        // dbname is not defined in constructor
        $this->mysqli = new mysqli( $this->host, $this->user, $this->pass );    
    }

    function __get( $dbname ) 
    {
        // if dbname is different, and select_db() is succesfull, save current dbname
        if ( $this->dbname !== $dbname && $this->mysqli->select_db( $dbname ) ) {
            $this->dbname = $dbname;
        }

        // return connection
        return $this->mysqli;
    }
}


// examples
$db = new Database();

$result = $db->db1->query( "SELECT DATABASE()" );
print_r( $result->fetch_row() );

$result = $db->db2->query( "SELECT DATABASE()" );
print_r( $result->fetch_row() );

$result = $db->{'dbname with spaces'}->query( "SELECT DATABASE()" );
print_r( $result->fetch_row() );
$con1 = mysql_connect($hostname, $username, $password); 
$con2 = mysql_connect($hostname, $username, $password, true); 

mysql_select_db('database1', $con1);
mysql_select_db('database2', $con2);

然后查询数据库 1 传递第一个 link 标识符:

mysql_query('select * from tablename', $con1);

对于数据库 2,传递第二个:

mysql_query('select * from tablename', $con2);

为什么需要两个连接?两个数据库的pros/advantages其实主要是性能问题。但是,如果您在同一台机器上,实际上您拥有的唯一优势就是更清晰的分离。所以最好使用一个 DB,为 table 使用两个不同的前缀。 所以你用前缀而不是数据库来分隔不同的数据。

改用 php 5 版本支持的 PDO mysql connect