Как создать переключатель режима для PHP PDO?

В настоящее время я использую PHP PDO для доступа к моей базе данных. Это все работает абсолютно нормально и денди. Однако я собираюсь добавить реплики чтения в настройки своего сервера, поэтому я хочу соответствующим образом скорректировать свой код.

Мой текущий план действий состоит в том, чтобы хранить массив сведений об учетных данных базы данных. Один набор «чтение и запись» для основной базы данных MySQL и любое количество учетных данных для «реплики чтения».

Что я хочу сделать, так это добавить в класс PDO метод под названием «режим», в котором передается режим, например «чтение» или (по умолчанию) «запись». Передавая это через (например, $dbh->mode("read"); ), он может искать детали реплики случайного чтения (не беспокоясь, какая) и использовать эти детали для соединения. Затем, когда я закончу чтение из своих реплик, сделайте еще один $dbh->mode("default"), чтобы вернуть его в режим записи, в результате чего я могу использовать INSERT, UPDATE и т. д.

Можно ли это сделать без простого уничтожения объекта PDO и создания нового? Можно ли просто изменить детали подключения после того, как объект уже существует?

Пока у меня есть следующее (это почти ничего, но решил, что это начало).

Class SwitchablePDO extends PDO
{
    public function mode($mode = "default") 
    {
        // Use the credentials for my master read and write server by default

        if($mode == "read")
        {
            // Use one the credentials for my read replicas (randomly choose)
        }

    }
}

Любая помощь по этому поводу будет оценена по достоинству!


person Schodemeiss    schedule 27.07.2012    source источник
comment
Это необходимо? Я думаю, что большинство людей использовали бы пару пользователей БД для этого (один, который может только читать, и один, который имеет полный доступ), а затем использовали бы отдельное соединение с БД для каждого пользователя.   -  person Ozzy    schedule 27.07.2012
comment
Однако это не распределит нагрузку на реплики чтения. Детали подключения буквально разные для каждой реплики чтения. И если бы мне нужно было просто создавать новый объект PDO каждый раз, когда я хочу переключиться на чтение или запись, мне все еще нужен способ сделать это. Этот способ (надеюсь) позволит мне иметь только один объект соединения/экземпляр моего класса за раз, а не использовать $dbh_write-›query() и $dbh_read-›query().   -  person Schodemeiss    schedule 27.07.2012


Ответы (2)


Я бы предпочел настроить совершенно разные объекты подключения к базе данных, чем иметь дело с режимом. Используя режим, вы неизбежно столкнетесь с ситуацией, когда фрагмент кода не устанавливает режим и полагается на режим предыдущего фрагмента кода, и произойдет сбой при вызове в другом контексте. Это известно как последовательное связывание.

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

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

person Louis-Philippe Huberdeau    schedule 27.07.2012

Создайте отдельные классы для режима чтения и записи, которые затем, в свою очередь, назначьте частные/защищенные свойства в вашем классе SwitchablePDO. Затем вызов mode() должен просто установить, какое свойство использовать. Вот некоторый псевдокод:

class WriteablePDO extends PDO
{
    // methods
}

class ReadablePDO extends PDO
{
    // methods
}

class SwitchablePDO
{
    protected $_mode = 'read'; // default
    protected $_read;
    protected $_write;

    public function __construct()
    {
        $this->_read = new ReadablePDO();
        $this->_write = new WriteablePDO();
    }

    public function mode($key)
    {
        if ($key === 'read')
        {
            $this->_mode = '_read';
        }
        elseif ($key === 'write')
        {
            $this->_mode = '_write';
        }
    }

    public function __call($method, $arguments)
    {
        return call_user_func_array(array($this->{$this->_mode}, $method), $arguments);
    }

}
person Narf    schedule 27.07.2012