MySQLマスター/スレーブ構成を活用するコアを取得する方法は?


21

MySQLマスター/スレーブレプリケーションが機能しないという質問とその回答を読みました。

スレーブデータベースの使用は、Drupalコアではほとんど実装されていません。独自のモジュールを開発している場合、db_queryの呼び出しでは、$ options配列を使用してスレーブデータベースを使用することを指定する必要があります。この配列の設定方法については、DatabaseConnection :: defaultOptionsを参照してください。

子猫殺さずにコアをハッキングして、スレーブSELECTクエリを取得db_query()およびdb_select()作成する方法はありますか?

デフォルトでは、これらの関数は、スレーブにクエリするように特に指示されない限り、マスターにクエリを実行します(APIを参照)。db_query($query, $args, array('target' => 'slave'))これを達成するためにスレーブとコア(およびすべてのモジュール)をクエリするために記述する必要があります。

検索(スレーブ部分を参照)とアグリゲーターのみがこれを活用しているようです。

編集: 10月25日
プレスフロー7が出ているのを見ましたが、今それが大いに役立つかどうかわかりません。
何か関連するものが見つからなかったので、答えを得るのを助けるためにちょっとした賞金を試しましょう。

編集: 10月31日
主に、このトピックに関するCrellのコメントを心配しています:スレーブをどうするか?
SELECTに、スレーブにクエリを送信する場合、レプリケーションの遅延で何が起こるかnode_load()、新しいノードを保存した直後にやりたいことがあるという事実に問題があります。

回答:


17

現在、これをどのように実装していますか。

まず、次のようにSelectQueryExtenderクラスを設定する必要があります。

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');
  }
}

それができたら、他のすべてのクエリを取得してエクステンダーを拡張するだけです。:)それが理にかなっている場合。これがスニペットです。

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

そして今、すべてのSelectQueryがスレーブにヒットします;-)これが私がこれを達成できる唯一の方法です。とにかくそれはうまく機能します。

また、カスタムモジュールにこれがある場合は、SlaveTargetをファイルSlaveTarget.incに設定し、モジュール情報ファイルにfiles [] = SlaveTarget.incを追加できます。


こんにちはエリック、あなたの答えに感謝します、主に私が心配しているのはこのスレッドです:奴隷をどうするか?そして、スレーブに関するCrellさんのコメント。だから、どんなケースで解安全なのですか?あなたは、いくつかの制限でくださいSELECTクエリを?レプリケーションの遅延と、保存した直後にノードをロードすると問題が発生する可能性があるという事実にどのように対処しますか?
-tostinni

これにより、選択クエリでのみデータベースがスレーブに変更されます。これは、クエリがdb_queryではなくSelectQueryで記述されている場合にのみ発生するため、スレーブを対象とすることを心配して挿入または更新する必要はありません。これを3つの巨大な実稼働環境で問題なく実行しています。私の場合、mysqlのレプリケーションはほとんど瞬時に行われるので、あまり心配していませんが、特定の環境ではそれが小さな問題になることがわかります。
エリクドゥラン

あなたの答えをありがとう、それは素晴らしい解決策です。これが私たちの環境で実行可能かどうかを確認します。
-tostinni

エリック、このコードはcontribまたはsandboxモジュールとしてどこかにありますか?
ポールm

@ paul-m:drupal.org/project/autoslaveを参照してください。
smokris

5

AutoSlaveモジュールリダイレクトSELECTクエリ読み取り専用レプリカントのデータベースを、そしてそれは、アカウントの複製遅れになります。

モジュールのドキュメントによると、次のすべての条件に該当する場合にのみ読み取り専用レプリカントを使用します。

  1. クエリは、選択クエリです
  2. 選択クエリ内のテーブルは、要求中に、想定されるレプリケーションラグ内に書き込まれていません
  3. トランザクションは開始されていません
  4. 選択クエリのテーブルは、ドライバー設定の「テーブル」オプションで指定されていません
  5. ロックが開始されていません(コアdb-lockおよびmemcache-lockがサポートされています)

1

最近のDrupal BADcamp Pressflowで聞いたことから、マスター/スレーブ構成が必要な場合に進む方法です。DBとしてはMysqlに制限されます。また、doの「高性能グループ」をチェックアウトします


1
現在Pressflow 7 = D7、PressflowがD7がしないことは(まだ)何もありません:(
tostinni

1

Drupal 7のデータベース抽象化レイヤーで行われた驚くべき作業はすべて行われていますが、Drupalコアをそのまま使用するのは驚くほど困難です。他の人が言ったように、AutoSlaveはオプションですが、これを行うのはそれほど難しいと信じている私の頑固な拒否のために私が試みたものではありませんが。

私が見つけたより簡単な解決策は次のとおりです。すべて SELECTのsをスレーブサーバーにルーティングするselect.incには、コアincludes/database/mysqlディレクトリ内に次の内容のタイトルのファイルを作成します。

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

この方法にはいくつかのリスクがあります。

  1. このメソッドはすべて SELECTのs をハイジャックし、それらをスレーブに転送します。これにより、レプリケーションに遅れがある場合は間違いなく問題が発生します。その文章をもう一度読んでください。
  2. Drupalコアをアップグレードすると、このファイルが削除される可能性があります。
  3. Drupalコアが独自includes/database/mysql/select.incに出荷を開始する場合、アップグレード中にファイルが上書きされ、Drupalコアに同梱されるselect.incの独自のパッチバージョンの維持を開始する必要があります。

settings.phpでスレーブサーバーが指定されていない場合、上記のコードは問題を引き起こしません。マスターサーバーを使用すると、引き続き正常に低下します。


はい、接続が「スレーブ」に設定できる場合でも表示されます。クエリ自体にtarget => 'slave'オプションが設定されていない場合、デフォルトの接続で実行されます。query_alterレベルで接続ターゲットをより簡単に設定するのは簡単ではありません。
デビッドトーマス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.