【问题标题】:Pros and cons of connecting more than one database in single script在单个脚本中连接多个数据库的优缺点
【发布时间】:2015-05-19 11:03:14
【问题描述】:

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

我已经在 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) 这样做会是不好的做法吗?它会消耗更多的对象吗?是否应该要求我们关闭第一个?

【问题讨论】:

标签: php mysql sql database database-connection


【解决方案1】:

1) 是否可以在一个脚本中连接多个数据库?

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

2) 不应该用 mysql_close 关闭一个连接并打开一个新连接,而是应该同时打开两个连接,用户可以使用任何数据库中的任何表?

使用 mysql_pconnect 等持久数据库连接

3)如果可能的话,这有什么缺点?会创建两个对象,这会产生问题吗?

我认为除了增加服务器负载之外不会产生任何问题。

【讨论】:

  • 永远不要使用持久连接。 stackoverflow.com/questions/3332074/…
  • @DavidSoussan 感谢您分享该链接。不知道那个。但我不同意你的结论,那就是永远不要使用它。该链接警告注意事项,但也提供解决方案。
  • 在使用 SQL 30 年和使用 MySQL 15 年后,我可以说我从未见过持久连接是答案的情况。它们听起来对平面文件程序员很有吸引力。当您遇到真正的性能瓶颈时,请担心这类事情。我敢打赌,当你这样做时,问题不会是数据库连接开销
【解决方案2】:

你可以这样使用

$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);

【讨论】:

  • 感谢您的回复!是否有任何特定理由为与 $db2 的连接添加 true ?
  • 如果您不为第二个数据库传递 true,那么它将只为第一个数据库建立连接,因此必须将第四个参数传递为第二个数据库的 true
  • @Nikul - 想在这里纠正你,你说过“它只会为第一个数据库建立连接,因此有必要将第四个参数传递为第二个数据库的真值”。添加 true 背后的意义是不要让第二个连接覆盖第一个连接。如果你不添加 true 它将做什么是它将覆盖 db1 与 db2 的连接。
【解决方案3】:

你试过了吗?

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

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 为什么投反对票?好的,答案很简短,但实际上它是这里最好的答案之一。
    【解决方案5】:

    Q:在不关闭之前的数据库的情况下连接其他数据库有什么缺点?

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

    问:这样做是否合适?如果不多次在每个脚本中打开此连接,最好的方法是什么?我希望这仅在核心 php 中完成,因为我已经在 codeigniter 中知道了这一点。

    单向会话,但您不能在会话中存储数据库连接。读入PHP.net这个警告:“某些类型的数据不能被序列化,因此存储在会话中。它包括资源变量或具有循环引用的对象(即对象将自身的引用传递给另一个对象)。” MySQL 连接就是这样一种资源。

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

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

    参考:

    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

    【讨论】:

    • 这实际上回答了所提出的问题。
    【解决方案6】:

    使用多个数据库的最佳方式是使用 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 个数据库

    【讨论】:

      【解决方案7】:

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

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

      $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

      【讨论】:

        【解决方案8】:

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

        但要直接解决您的问题:

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

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

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

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

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

        【讨论】:

          【解决方案9】:

          打开 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 表。

          【讨论】:

          • 所以你的意思是说,在上述情况下,如果你已经连接到 db1,你不需要连接到 db2 吗?它会自动访问 db2 的表?
          • 是的,如果您使用我在示例中显示的 database.table 表示法。当然,用户必须对两种模式都拥有必要的权限。
          • @David Soussan,不。您需要意识到,要获得用于执行查询的数据库连接句柄,您必须指定数据库名称,无论您使用 mysqli 扩展还是 PDO。那么,如何在一个连接句柄中引用 db1 和 db2 呢?你说'当然用户必须对两个模式都有必要的权限',也许你应该先展示如何进行这种连接,然后我们可以学习。
          • @StephenAdelakun 你错了。大卫是对的。在 MySQL 中,您可以在同一连接甚至同一查询中引用跨不同模式的所有可访问表。这个答案是最相关的。您在连接期间指定的架构将是您选择的(默认)架构,这意味着未指定架构的查询将假定一个。但是你仍然可以在查询中说schemaname.tablename 来引用另一个模式中的表。
          • @nl-x,我想我现在看到了混乱。因此,您必须已授予用户对这两者的访问权限。好吧,我错过了这一点。事实上,我以前从未这样做过。在这种情况下,大卫是对的。感谢 nl-x 指出这一点。
          【解决方案10】:

          使用 mysqli_connect 代替 mysql_connect

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

          【讨论】:

          • $Db1 = new mysqli($hostname,$username,$password,$db_name1); // 这是 DB 1 的连接 1
          • $Db2 = new mysqli($hostname,$username,$password,$db_name2); // 这是 DB 2 的连接 2
          【解决方案11】:

          这是一个简单的类,它会在需要时自动选择所需的数据库。

          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() );
          

          【讨论】:

            【解决方案12】:
            $con1 = mysql_connect($hostname, $username, $password); 
            $con2 = mysql_connect($hostname, $username, $password, true); 
            
            mysql_select_db('database1', $con1);
            mysql_select_db('database2', $con2);
            

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

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

            对于数据库 2,通过第二个:

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

            【讨论】:

              【解决方案13】:

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

              【讨论】:

                【解决方案14】:

                使用 php 5 版本支持的 PDO 代替 mysql connect

                【讨论】:

                • 为什么?你应该提到这一点!我认为这与 PDO/MySql 无关
                猜你喜欢
                • 2013-09-25
                • 1970-01-01
                • 2023-03-08
                • 1970-01-01
                • 2010-12-02
                • 1970-01-01
                • 1970-01-01
                • 2012-02-21
                • 1970-01-01
                相关资源
                最近更新 更多