Como obter o núcleo para alavancar uma configuração de mestre / escravo do MySQL?

21

Eu li esta pergunta A replicação master / slave do MySQL não está funcionando e sua resposta:

O uso de bancos de dados escravos mal é implementado no núcleo do Drupal. Se você estiver desenvolvendo seus próprios módulos, as chamadas para db_query precisam especificar que eles desejam usar o banco de dados escravo usando a matriz $ options. Consulte DatabaseConnection :: defaultOptions para saber como definir essa matriz.

Existe uma maneira de matar gatinhos que invadiram o núcleo para obter db_query()e db_select()fazer mais consultas SELECT de escravos?

Por padrão, essas funções consultam o mestre, a menos que seja especificamente solicitado a consultar o escravo (consulte sua API). Você precisa escrever db_query($query, $args, array('target' => 'slave'))para consultar o escravo e o núcleo (e todos os módulos) não foram gravados para conseguir isso.

Somente a pesquisa (veja a parte escrava) e o agregador parecem alavancar isso.

Edit: 25 de outubro
Vi o pressflow 7 sair, mas não tenho certeza se isso ajuda muito agora.
Eu não encontrei algo relevante, então vamos tentar um pouco de recompensa para ajudar a obter uma resposta.

Edit: 31 de outubro.
Estou preocupado principalmente com os comentários de Crell sobre este tópico: O que fazer com os escravos? .
Principalmente, existem problemas se eu enviar SELECTconsultas para o escravo, o que acontece com os atrasos na replicação e o fato de que talvez eu queira fazer isso node_load()logo após salvar um novo nó.

tostinni
fonte

Respostas:

17

Aqui está como eu implemento isso atualmente.

Primeiro, você precisa configurar uma classe 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');
  }
}

Depois de ter isso, tudo o que você precisa fazer é obter todas as outras consultas para estender o extensor. :) se isso faz sentido. Aqui está o trecho.

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

E agora todo o seu SelectQuery atingiu o escravo ;-) Esta é a única maneira de conseguir isso. De qualquer forma, funciona muito bem.

Além disso, se você tiver isso em um módulo personalizado, poderá configurar o SlaveTarget para que esteja no arquivo SlaveTarget.inc e adicionar um arquivo [] = SlaveTarget.inc ao arquivo de informações do módulo.

ericduran
fonte
Olá Eric, obrigado pela sua resposta, o que mais me preocupa é este tópico: O que fazer com os escravos? e o comentário de Crell sobre o escravo . Então, sua solução é segura em qualquer caso? Você restringe algumas SELECTconsultas? Como você lida com os atrasos na replicação e o fato de carregar um nó logo depois de salvo pode causar problemas?
tostinni
Isso está alterando o banco de dados para escravo apenas nas consultas Select. Isso acontece apenas quando a consulta foi gravada com SelectQuery e não db_query, portanto, não é necessário se preocupar e inserir ou atualizar o destino do escravo. Estamos executando isso em três grandes ambientes de produção sem problemas. Eu não tenho me preocupado muito com a replicação do mysql, já que é quase instantânea (no meu caso), mas posso ver como isso pode ser um pequeno problema em alguns ambientes.
ericduran
Obrigado por suas respostas, é uma ótima solução, vou ver se isso é viável em nosso ambiente.
tostinni
Eric, esse código existe em algum lugar como um módulo contrib ou sandbox?
paul-m
@ paul-m: consulte drupal.org/project/autoslave .
22412 smokris
5

O módulo AutoSlave redireciona SELECTconsultas para bancos de dados replicantes somente leitura e leva em consideração o atraso na replicação.

De acordo com os documentos do módulo, ele usa apenas o replicante somente leitura quando todas as seguintes condições forem verdadeiras:

  1. A consulta é uma consulta selecionada
  2. As tabelas na consulta de seleção não foram gravadas durante a solicitação e dentro do atraso de replicação assumido
  3. Uma transação não foi iniciada
  4. As tabelas na consulta de seleção não são especificadas na opção 'tabelas' nas configurações do driver
  5. Um bloqueio não foi iniciado (core db-lock e memcache-lock suportado)
smokris
fonte
1

pelo que ouvi no recente Drupal BADcamp Pressflow, é o caminho a percorrer, se você deseja configurações mestre / escravo. Você ficará limitado ao Mysql como o banco de dados. Além disso, confira o " grupo de alto desempenho " em

uwe
fonte
1
Atualmente Pressflow 7 = D7, ainda não há nada que o Pressflow faça que o D7 não :(
tostinni
1

Apesar de todo o incrível trabalho realizado na camada de abstração do banco de dados no Drupal 7, isso ainda é surpreendentemente difícil de ser feito com o núcleo do Drupal pronto para uso. Como outros já mencionaram, o AutoSlave é uma opção, embora não tenha tentado devido à minha teimosa recusa em acreditar que deveria ser tão difícil fazer isso.

Uma solução mais simples que encontrei é a seguinte. Para rotear todos os SELECT s para o servidor escravo, crie um arquivo intitulado select.incdentro do includes/database/mysqldiretório principal com o seguinte conteúdo:

<?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".
 */

Existem alguns riscos com este método:

  1. Esse método seqüestrará todos os se SELECT direcionará ao escravo, o que sem dúvida causará problemas se houver algum atraso na replicação. Leia essa frase novamente.
  2. Quando você atualiza o núcleo do Drupal, é possível que esse arquivo seja excluído.
  3. Se o núcleo do Drupal alguma vez começar a ser enviado por conta própria includes/database/mysql/select.inc, seu arquivo será substituído durante a atualização e você terá que começar a manter sua própria versão corrigida do select.inc que acompanha o núcleo do Drupal.

Se você não possui nenhum servidor escravo especificado em settings.php, o código acima não causará problemas. Ainda será degradado normalmente para o uso do servidor mestre .

q0rban
fonte
Sim, embora a conexão possa ser definida como "escrava", se a consulta em si não tiver a target => 'slave'opção definida, ela ainda será executada na conexão padrão. É uma dor, não é mais fácil definir o destino da conexão mais facilmente no query_alternível.
9788 David Guetta