¿Cómo obtener el núcleo para aprovechar una configuración maestro / esclavo MySQL?


21

Leí esta pregunta La replicación maestro / esclavo MySQL no funciona y su respuesta:

El uso de bases de datos esclavas apenas se implementa en el núcleo de Drupal. Si está desarrollando sus propios módulos, las llamadas a db_query deben especificar que desean utilizar la base de datos esclava utilizando la matriz $ options. Vea DatabaseConnection :: defaultOptions para saber cómo configurar esta matriz.

¿Hay alguna manera sin matar gatitos hackeando el núcleo para obtener db_query()y db_select()hacer más consultas SELECT esclavas?

Por defecto, estas funciones consultarán al maestro a menos que se le indique específicamente que consulte al esclavo (consulte su API). Debe escribir db_query($query, $args, array('target' => 'slave'))para consultar al esclavo y el núcleo (y todos los módulos) no están escritos para lograr esto.

Solo buscar (ver la parte esclava) y el agregador parece aprovechar esto.

Editar: 25 de octubre
Vi que pressflow 7 está fuera, pero no estoy seguro de si ayuda mucho en este momento.
No he encontrado algo relevante, así que intentemos una pequeña recompensa para ayudar a obtener una respuesta.

Editar: 31 de octubre
. Estoy principalmente preocupado por los comentarios de Crell sobre este tema: ¿Qué hacer con los esclavos? .
Principalmente, ¿hay problemas si envío SELECTconsultas al esclavo, qué sucede con los retrasos en la replicación y el hecho de que tal vez quiera hacer un node_load()poco después de guardar un nuevo nodo?

Respuestas:


17

Así es como actualmente implemento esto.

Primero debe configurar una clase SelectQueryExtender como esta:

class SlaveTarget extends SelectQueryExtender {
  public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
    if ($connection->getTarget() != 'slave') {
      $connection = Database::getConnection('slave', $connection->getKey());
    }
    parent::__construct($query, $connection);
    $this->addTag('SlaveTarget');
  }
}

Una vez que tenga eso, todo lo que tiene que hacer es obtener todas las demás consultas para extender el extensor. :) Si eso tiene sentido. Aquí está el fragmento.

/**
 * Implements hook_query_alter().
 */
function example_query_alter(QueryAlterableInterface $query) { 
  if (is_a($query, 'SelectQuery') && !$query->hasTag('SlaveTarget')) {
    $query->extend('SlaveTarget');
  }
}

Y ahora todo su SelectQuery golpeó al esclavo ;-) Esta es la única forma en que he podido lograr esto. De todos modos funciona muy bien.

Además, si tiene esto en un módulo personalizado, puede configurar SlaveTarget para que esté en el archivo SlaveTarget.inc y agregar un archivo [] = SlaveTarget.inc a su archivo de información del módulo.


Hola Eric, gracias por tu respuesta, lo que más me preocupa es este hilo: ¿Qué hacer con los esclavos? y el comentario de Crell sobre el esclavo . Entonces, ¿su solución es segura en cualquier caso? ¿Limitan algunas SELECTconsultas? ¿Cómo lidiar con los retrasos en la replicación y el hecho de que cargar un nodo justo después de guardarlo puede causar problemas?
tostinni

Esto está cambiando la base de datos a esclavo solo en consultas Select. Esto solo ocurre cuando la consulta se ha escrito con SelectQuery y no con db_query, por lo que no es necesario preocuparse e insertar o actualizar el destino del esclavo. Estamos ejecutando esto en 3 entornos de producción enormes sin ningún problema. No me he preocupado mucho por la replicación de mysql, ya que es casi instantánea (en mi caso), pero puedo ver cómo podría ser un problema pequeño en ciertos entornos.
ericduran

Gracias por sus respuestas, es una gran solución, veré si esto es viable en nuestro entorno.
tostinni

Eric, ¿está este código en algún lugar como un módulo contrib o sandbox?
paul-m


5

El módulo AutoSlave redirige las SELECTconsultas a bases de datos replicantes de solo lectura y tiene en cuenta el retraso de la replicación.

Según los documentos del módulo, solo utiliza el replicante de solo lectura cuando se cumplen todas las condiciones siguientes:

  1. La consulta es una consulta de selección
  2. Las tablas en la consulta de selección no se han escrito durante la solicitud y dentro del retraso de replicación supuesto
  3. No se ha iniciado una transacción.
  4. Las tablas en la consulta de selección no se especifican en la opción 'tablas' en la configuración del controlador
  5. No se ha iniciado un bloqueo (se admite core db-lock y memcache-lock)

1

por lo que escuché en el reciente Drupal BADcamp Pressflow es el camino a seguir si desea configuraciones maestro / esclavo. Estarás limitado a Mysql como DB. Además, verifique el " grupo de alto rendimiento " en do


1
Actualmente Pressflow 7 = D7, no hay nada (todavía) que Pressflow haga que D7 no :(
tostinni

1

A pesar de todo el increíble trabajo realizado en la capa de abstracción de la base de datos en Drupal 7, esto sigue siendo sorprendentemente difícil de hacer con el núcleo de Drupal listo para usar. Como otros han mencionado, AutoSlave es una opción, aunque no una que he intentado debido a mi obstinada negativa a creer que debería ser tan difícil hacerlo.

Una solución más simple que he encontrado es la siguiente. Para enrutar todos SELECT los correos electrónicos al servidor esclavo, cree un archivo titulado select.incdentro del includes/database/mysqldirectorio central con el siguiente contenido:

<?php

/**
 * @file
 * Select builder for MySQL database engine, routing all SELECTs to the slave.
 */

/**
 * @addtogroup database
 * @{
 */

class SelectQuery_mysql extends SelectQuery {
  public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
    $key = $connection->getKey();
    $connection = Database::getConnection('slave', $key);
    $options['target'] = 'slave';
    parent::__construct($table, $alias, $connection, $options);
  }
}

/**
 * @} End of "addtogroup database".
 */

Existen algunos riesgos con este método:

  1. Este método secuestrará todos los correos electrónicos SELECTy los dirigirá al esclavo, lo que indudablemente causará problemas si tiene algún retraso en la replicación. Lee esa oración de nuevo.
  2. Cuando actualiza Drupal core, es posible que este archivo se elimine.
  3. Si el núcleo de Drupal comenzara a enviarse con el suyo includes/database/mysql/select.inc, su archivo se sobrescribiría durante la actualización, y tendría que comenzar a mantener su propia versión parcheada de select.inc que se envía con el núcleo de Drupal.

Si no tiene ningún servidor esclavo especificado en settings.php, el código anterior no causará ningún problema. Todavía se degradará con gracia al uso del servidor maestro .


Sí, parece que aunque la conexión se puede configurar como "esclava", si la consulta en sí no tiene la target => 'slave'opción establecida, se ejecutará en la conexión predeterminada. Es un dolor, no es más fácil establecer el objetivo de conexión más fácilmente en el query_alternivel.
David Thomas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.