Плюсы и минусы подключения более одной базы данных в одном скрипте

Допустим, у пользователя есть две базы данных, размещенные на одном хосте, и мне нужно подключиться к обеим из них, чтобы я мог использовать любую таблицу в любое время, не добавляя код подключения несколько раз.

Я реализовал это в 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) Будет ли это плохой практикой? Будет ли он потреблять больше предметов? Должны ли мы все равно закрывать первую?


person CodeWithCoffee    schedule 17.03.2015    source источник
comment
Поделитесь, пожалуйста, тем, что вы уже пробовали.   -  person Mithun    schedule 17.03.2015
comment
Отредактированный вопрос !! пожалуйста, проверьте   -  person CodeWithCoffee    schedule 17.03.2015
comment
Примечание: пожалуйста, не используйте mysql_* функции, они больше не поддерживаются и официально устарели. Узнайте о подготовленных операторах взамен и используйте PDO или MySQLi. Эта статья поможет вам принять решение.   -  person Michael Doye    schedule 17.03.2015
comment
они находятся в одном экземпляре и имеют разные имена баз данных?   -  person jbrahy    schedule 20.03.2015
comment
Это просто другое имя базы данных в одном экземпляре   -  person CodeWithCoffee    schedule 23.03.2015


Ответы (14)


Нет необходимости открывать 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.

person David Soussan    schedule 23.03.2015
comment
Значит, вы хотите сказать, что в приведенном выше случае, если вы уже подключились к db1, вам не нужно подключаться к db2? И он автоматически получит доступ к таблице db2? - person CodeWithCoffee; 23.03.2015
comment
Да, если вы используете нотацию database.table, как я показываю в моем примере. Конечно, у пользователя должны быть необходимые разрешения для обеих схем. - person David Soussan; 23.03.2015
comment
@David Soussan, Нет. Вы должны понимать, что для получения дескриптора подключения к базе данных, с помощью которого вы выполняете свои запросы, вы должны указать имя базы данных, независимо от того, используете ли вы расширение mysqli или PDO. Итак, как вы можете ссылаться на db1 и db2 в одном дескрипторе соединения? Вы сказали: «Конечно, у пользователя должны быть необходимые разрешения для обеих схем», может быть, вам сначала следует показать, как установить такое соединение, тогда мы сможем научиться. - person Stephen Adelakun; 24.03.2015
comment
@StephenAdelakun Вы ошибаетесь. Дэвид прав. В MySQL вы можете ссылаться на все доступные таблицы в разных схемах в одном и том же соединении и даже в одном и том же запросе. Этот ответ наиболее актуален. Схема, которую вы укажете во время соединения, будет вашей выбранной схемой (по умолчанию), то есть запросы, которые не указывают схему, будут считать ее. Но вы все равно можете указать schemaname.tablename в запросе для ссылки на таблицу в другой схеме. - person nl-x; 24.03.2015
comment
@ nl-x, думаю, теперь я вижу путаницу. Таким образом, вы должны предоставить пользователю доступ к обоим. Хорошо, я упустил этот момент. Собственно говоря, я никогда раньше этого не делал. В этом случае Дэвид был прав. Спасибо nl-x за указание на это. - person Stephen Adelakun; 24.03.2015

Вы пробовали это?

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

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

Зачем вам два подключения? Плюсы / преимущества двух баз данных на самом деле в первую очередь связаны с производительностью. Но если вы работаете на одной машине, единственное преимущество, которое у вас есть, - это более четкое разделение. Поэтому было бы лучше использовать одну БД с двумя разными префиксами для таблицы. Таким образом, вы разделяете разные данные по префиксу, а не по БД.

person Dave    schedule 25.03.2015

Вы можете сделать это, следуя объектно-ориентированному подходу.

Прежде всего создайте соединение с двумя базами данных:

$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.

person PHP Worm...    schedule 23.03.2015

Я не думаю, что проблема заключается в одновременном подключении к 2 БД, поскольку вы успешно это сделали (или знаете, как это сделать). Я могу понять это из вашего вопроса. Так что я не буду показывать, как это делать. При необходимости посмотрите другие ответы.

Но чтобы решить ваши проблемы напрямую:

  1. Будет ли это плохой практикой? Как правило, вам следует по возможности избегать двух одновременных дескрипторов подключения к БД. Если вам нужно получить данные только из одной БД и использовать их для выполнения каких-либо действий с другой, лучше всего поместить данные из DB1 в соответствующие переменные PHP, закрыть соединение; затем сделайте второе подключение. Это будет дешевле, чем держать открытыми 2 соединения с БД одновременно. Однако, если вы делаете что-то вроде INSERT INTO db1.table SELECT FROM db2.table И ТАКЖЕ НЕОБХОДИМО COMMIT ИЛИ ОТКАТ в зависимости от успеха или неудачи некоторых запросов, то, AFAIK, вам нужно держать оба соединения открытыми до завершения ваших процессов. Видите ли, всегда есть компромиссы. Таким образом, вы решаете, исходя из потребностей вашего приложения, и несете расходы.

В качестве практического примера этого сценария я однажды работал над проектом, в котором мне нужно было ВЫБРАТЬ таблицу1, ВСТАВИТЬ В таблицу2, если INSERT завершится успешно, я удаляю все строки из таблицы1, если DELETE не удается, я откатываю операцию INSERT потому что данные не могут находиться в двух таблицах одновременно.

Конечно, в моем собственном случае использовалась только одна БД, поэтому второе соединение не требовалось. Но если предположить, что две таблицы находятся в разных БД, это может быть похоже на вашу ситуацию.

  1. Будет ли он потреблять больше предметов? Никакие другие объекты, кроме указанных в пункте 1 выше, а именно подключение к БД, не обрабатываются в соответствии с вашим вопросом.

  2. Должны ли мы в любом случае требовать обязательного закрытия первого? Еще раз, в зависимости от потребностей вашего приложения.

person Stephen Adelakun    schedule 23.03.2015

Вместо mysql_connect используйте mysqli_connect.

mysqli предоставляет возможность одновременного подключения нескольких баз данных.

person kaushik    schedule 23.03.2015
comment
$ Db1 = новый mysqli ($ hostname, $ username, $ password, $ db_name1); // это соединение 1 для БД 1 - person kaushik; 23.03.2015
comment
$ Db2 = новый mysqli ($ hostname, $ username, $ password, $ db_name2); // это соединение 2 для БД 2 - person kaushik; 23.03.2015

В: Какие недостатки существуют при подключении к другой базе данных без закрытия предыдущей базы данных?

A: Когда вы подключаетесь к серверу базы данных, физически назначаете ресурсы для взаимодействия с вами, если две базы данных находятся на одном сервере, вы без необходимости используете ресурсы, которые могут использоваться для адресации других подключений или других действий. Следовательно, вы будете правы, закройте связи, которые не нужно продолжать использовать.

В: Это подходящая практика? Как лучше всего сделать это, не открывая это соединение в каждом скрипте несколько раз? Я хочу, чтобы это было сделано только в core 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

Не удается передать соединение mysqli в сеансе в php

person Adrian Cid Almaguer    schedule 20.03.2015
comment
Это фактически отвечает на заданный вопрос. - person Izion; 29.05.2015

1) Можно ли в одном скрипте подключиться к нескольким базам данных?

Да, мы можем создать несколько идентификаторов ссылок MySQL в одном скрипте.

2) Не должно быть похоже на закрытие одного соединения с mysql_close и открытие нового, скорее оба соединения должны открываться одновременно, и пользователь может использовать любую таблицу из любой базы данных?

Используйте постоянные подключения к базе данных, например mysql_pconnect

3) Если возможно, то в чем может быть недостаток? Будет ли создано два объекта, и это создаст проблему?

Я не думаю, что это создаст какие-либо проблемы, кроме увеличения нагрузки на сервер.

person Prabhat Kumar    schedule 17.03.2015
comment
НИКОГДА не используйте постоянные соединения. stackoverflow.com/questions/3332074/ - person David Soussan; 23.03.2015
comment
@DavidSoussan Спасибо, что поделились этой ссылкой. Не знал этого. Но я не согласен с вашим выводом о том, что НИКОГДА не используйте его. Ссылка предупреждает о предостережениях, но также дает решения. - person nl-x; 24.03.2015
comment
После 30 лет использования SQL и 15 лет работы с MySQL я могу сказать, что никогда не видел ситуации, когда постоянные соединения были бы решением. Они просто кажутся привлекательными для программистов плоских файлов. Беспокойтесь о таких вещах, когда вы сталкиваетесь с реальным узким местом в производительности. Готов поспорить, что когда вы это сделаете, проблема будет не в накладных расходах на соединение с базой данных. - person David Soussan; 24.03.2015

Вы можете использовать это так

$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);
person Nikul    schedule 17.03.2015
comment
Спасибо за ответ !! Есть ли какая-то особая причина для добавления истины для соединения с $ db2? - person CodeWithCoffee; 17.03.2015
comment
Если вы не передадите истину для второй базы данных, тогда соединение будет установлено только для первой базы данных, поэтому необходимо передать четвертый параметр как истину для второй базы данных. - person Nikul; 17.03.2015
comment
@Nikul - хотел бы просто исправить вас здесь, где вы сказали, что он будет устанавливать соединение только для первой базы данных, поэтому необходимо передать четвертый параметр как истинный для второй базы данных. Смысл добавления истины в том, чтобы не позволить второму соединению переопределить первое сделанное соединение. Если вы не добавите истину, он будет отменять соединение db1 с db2. - person Rakesh Lamp Stack; 21.03.2015

Лучший способ использовать несколько баз данных - использовать функции 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 баз данных

person Ivijan Stefan Stipić    schedule 21.03.2015

Используйте PDO, поддерживаемый версией php 5, вместо mysql connect

person Lerry    schedule 08.04.2015
comment
Почему? вы должны упомянуть об этом! Я не думаю, что это связано с PDO / MySql - person rohitcoder; 08.07.2020

Вот простой класс, который автоматически выбирает необходимую базу данных при необходимости.

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() );
person Danijel    schedule 23.03.2015

$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);
person Mohit maru    schedule 24.03.2015

если у пользователя mysql есть разрешение на две базы данных, вы можете присоединиться к двум таблицам из двух баз данных и т. д .:

SELECT database1.table.title title1,database2.table.title title2 
FROM database1.table
INNER JOIN database2.table 
ON (database1.table.id=database2.table.id)
person Javad Khodadadi    schedule 19.03.2015
comment
Почему отрицательные голоса? Хорошо, ответ довольно короткий, но на самом деле здесь один из лучших. - person nl-x; 24.03.2015