Issue #2275877 by Mixologic, duellj, Les Lim, Xano, David Strauss: Replace master/slave terminology with primary/replica.
parent
7fdb267c9c
commit
b1b3b2b886
|
@ -134,8 +134,8 @@ Drupal 7.0, 2011-01-05
|
|||
* Fully rewritten database layer utilizing PHP 5's PDO abstraction layer.
|
||||
* Drupal now requires MySQL >= 5.0.15 or PostgreSQL >= 8.3.
|
||||
* Added query builders for INSERT, UPDATE, DELETE, MERGE, and SELECT queries.
|
||||
* Support for master/slave replication, transactions, multi-insert queries,
|
||||
and other features.
|
||||
* Support for primary/replica replication, transactions, multi-insert
|
||||
queries, and other features.
|
||||
* Added support for the SQLite database engine.
|
||||
* Default to InnoDB engine, rather than MyISAM, on MySQL when available.
|
||||
This offers increased scalability and data integrity.
|
||||
|
|
|
@ -308,11 +308,11 @@ services:
|
|||
- [initLanguageManager]
|
||||
tags:
|
||||
- { name: service_collector, tag: string_translator, call: addTranslator }
|
||||
database.slave:
|
||||
database.replica:
|
||||
class: Drupal\Core\Database\Connection
|
||||
factory_class: Drupal\Core\Database\Database
|
||||
factory_method: getConnection
|
||||
arguments: [slave]
|
||||
arguments: [replica]
|
||||
typed_data_manager:
|
||||
class: Drupal\Core\TypedData\TypedDataManager
|
||||
parent: default_plugin_manager
|
||||
|
@ -707,8 +707,8 @@ services:
|
|||
batch.storage:
|
||||
class: Drupal\Core\Batch\BatchStorage
|
||||
arguments: ['@database']
|
||||
slave_database_ignore__subscriber:
|
||||
class: Drupal\Core\EventSubscriber\SlaveDatabaseIgnoreSubscriber
|
||||
replica_database_ignore__subscriber:
|
||||
class: Drupal\Core\EventSubscriber\ReplicaDatabaseIgnoreSubscriber
|
||||
tags:
|
||||
- {name: event_subscriber}
|
||||
country_manager:
|
||||
|
|
|
@ -296,7 +296,7 @@ function db_query_temporary($query, array $args = array(), array $options = arra
|
|||
* A new Insert object for this connection.
|
||||
*/
|
||||
function db_insert($table, array $options = array()) {
|
||||
if (empty($options['target']) || $options['target'] == 'slave') {
|
||||
if (empty($options['target']) || $options['target'] == 'replica') {
|
||||
$options['target'] = 'default';
|
||||
}
|
||||
return Database::getConnection($options['target'])->insert($table, $options);
|
||||
|
@ -314,7 +314,7 @@ function db_insert($table, array $options = array()) {
|
|||
* A new Merge object for this connection.
|
||||
*/
|
||||
function db_merge($table, array $options = array()) {
|
||||
if (empty($options['target']) || $options['target'] == 'slave') {
|
||||
if (empty($options['target']) || $options['target'] == 'replica') {
|
||||
$options['target'] = 'default';
|
||||
}
|
||||
return Database::getConnection($options['target'])->merge($table, $options);
|
||||
|
@ -332,7 +332,7 @@ function db_merge($table, array $options = array()) {
|
|||
* A new Update object for this connection.
|
||||
*/
|
||||
function db_update($table, array $options = array()) {
|
||||
if (empty($options['target']) || $options['target'] == 'slave') {
|
||||
if (empty($options['target']) || $options['target'] == 'replica') {
|
||||
$options['target'] = 'default';
|
||||
}
|
||||
return Database::getConnection($options['target'])->update($table, $options);
|
||||
|
@ -350,7 +350,7 @@ function db_update($table, array $options = array()) {
|
|||
* A new Delete object for this connection.
|
||||
*/
|
||||
function db_delete($table, array $options = array()) {
|
||||
if (empty($options['target']) || $options['target'] == 'slave') {
|
||||
if (empty($options['target']) || $options['target'] == 'replica') {
|
||||
$options['target'] = 'default';
|
||||
}
|
||||
return Database::getConnection($options['target'])->delete($table, $options);
|
||||
|
@ -368,7 +368,7 @@ function db_delete($table, array $options = array()) {
|
|||
* A new Truncate object for this connection.
|
||||
*/
|
||||
function db_truncate($table, array $options = array()) {
|
||||
if (empty($options['target']) || $options['target'] == 'slave') {
|
||||
if (empty($options['target']) || $options['target'] == 'replica') {
|
||||
$options['target'] = 'default';
|
||||
}
|
||||
return Database::getConnection($options['target'])->truncate($table, $options);
|
||||
|
@ -924,18 +924,21 @@ function db_change_field($table, $field, $field_new, $spec, $keys_new = array())
|
|||
*/
|
||||
|
||||
/**
|
||||
* Sets a session variable specifying the lag time for ignoring a slave server.
|
||||
* Sets a session variable specifying the lag time for ignoring a replica
|
||||
* server (A replica server is traditionally referred to as
|
||||
* a "slave" in database server documentation).
|
||||
* @see http://drupal.org/node/2275877
|
||||
*/
|
||||
function db_ignore_slave() {
|
||||
function db_ignore_replica() {
|
||||
$connection_info = Database::getConnectionInfo();
|
||||
// Only set ignore_slave_server if there are slave servers being used, which
|
||||
// is assumed if there are more than one.
|
||||
// Only set ignore_replica_server if there are replica servers being used,
|
||||
// which is assumed if there are more than one.
|
||||
if (count($connection_info) > 1) {
|
||||
// Five minutes is long enough to allow the slave to break and resume
|
||||
// Five minutes is long enough to allow the replica to break and resume
|
||||
// interrupted replication without causing problems on the Drupal site from
|
||||
// the old data.
|
||||
$duration = Settings::get('maximum_replication_lag', 300);
|
||||
// Set session variable with amount of time to delay before using slave.
|
||||
$_SESSION['ignore_slave_server'] = REQUEST_TIME + $duration;
|
||||
// Set session variable with amount of time to delay before using replica.
|
||||
$_SESSION['ignore_replica_server'] = REQUEST_TIME + $duration;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ class DatabaseStorage implements StorageInterface {
|
|||
*
|
||||
* @throws PDOException
|
||||
*
|
||||
* @todo Ignore slave targets for data manipulation operations.
|
||||
* @todo Ignore replica targets for data manipulation operations.
|
||||
*/
|
||||
public function delete($name) {
|
||||
$options = array('return' => Database::RETURN_AFFECTED) + $this->options;
|
||||
|
|
|
@ -35,8 +35,8 @@ abstract class Connection implements \Serializable {
|
|||
* The key representing this connection.
|
||||
*
|
||||
* The key is a unique string which identifies a database connection. A
|
||||
* connection can be a single server or a cluster of master and slaves (use
|
||||
* target to pick between master and slave).
|
||||
* connection can be a single server or a cluster of primary and replicas
|
||||
* (use target to pick between primary and replica).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -188,7 +188,7 @@ abstract class Connection implements \Serializable {
|
|||
* A given query can be customized with a number of option flags in an
|
||||
* associative array:
|
||||
* - target: The database "target" against which to execute a query. Valid
|
||||
* values are "default" or "slave". The system will first try to open a
|
||||
* values are "default" or "replica". The system will first try to open a
|
||||
* connection to a database specified with the user-supplied key. If one
|
||||
* is not available, it will silently fall back to the "default" target.
|
||||
* If multiple databases connections are specified with the same target,
|
||||
|
|
|
@ -159,8 +159,8 @@ abstract class Database {
|
|||
}
|
||||
// If the requested target does not exist, or if it is ignored, we fall back
|
||||
// to the default target. The target is typically either "default" or
|
||||
// "slave", indicating to use a slave SQL server if one is available. If
|
||||
// it's not available, then the default/master server is the correct server
|
||||
// "replica", indicating to use a replica SQL server if one is available. If
|
||||
// it's not available, then the default/primary server is the correct server
|
||||
// to use.
|
||||
if (!empty(self::$ignoreTargets[$key][$target]) || !isset(self::$databaseInfo[$key][$target])) {
|
||||
$target = 'default';
|
||||
|
@ -212,7 +212,7 @@ abstract class Database {
|
|||
final public static function parseConnectionInfo(array $info) {
|
||||
// If there is no "driver" property, then we assume it's an array of
|
||||
// possible connections for this target. Pick one at random. That allows
|
||||
// us to have, for example, multiple slave servers.
|
||||
// us to have, for example, multiple replica servers.
|
||||
if (empty($info['driver'])) {
|
||||
$info = $info[mt_rand(0, count($info) - 1)];
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ abstract class Database {
|
|||
/**
|
||||
* Instructs the system to temporarily ignore a given key/target.
|
||||
*
|
||||
* At times we need to temporarily disable slave queries. To do so, call this
|
||||
* At times we need to temporarily disable replica queries. To do so, call this
|
||||
* method with the database key and the target to disable. That database key
|
||||
* will then always fall back to 'default' for that key, even if it's defined.
|
||||
*
|
||||
|
|
|
@ -611,8 +611,8 @@ class ContentEntityDatabaseStorage extends ContentEntityStorageBase implements S
|
|||
try {
|
||||
parent::delete($entities);
|
||||
|
||||
// Ignore slave server temporarily.
|
||||
db_ignore_slave();
|
||||
// Ignore replica server temporarily.
|
||||
db_ignore_replica();
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$transaction->rollback();
|
||||
|
@ -669,8 +669,8 @@ class ContentEntityDatabaseStorage extends ContentEntityStorageBase implements S
|
|||
|
||||
$return = parent::save($entity);
|
||||
|
||||
// Ignore slave server temporarily.
|
||||
db_ignore_slave();
|
||||
// Ignore replica server temporarily.
|
||||
db_ignore_replica();
|
||||
return $return;
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
|
|
|
@ -135,8 +135,8 @@ class EntityDatabaseStorage extends EntityStorageBase {
|
|||
try {
|
||||
parent::delete($entities);
|
||||
|
||||
// Ignore slave server temporarily.
|
||||
db_ignore_slave();
|
||||
// Ignore replica server temporarily.
|
||||
db_ignore_replica();
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$transaction->rollback();
|
||||
|
@ -167,8 +167,8 @@ class EntityDatabaseStorage extends EntityStorageBase {
|
|||
try {
|
||||
$return = parent::save($entity);
|
||||
|
||||
// Ignore slave server temporarily.
|
||||
db_ignore_slave();
|
||||
// Ignore replica server temporarily.
|
||||
db_ignore_replica();
|
||||
return $return;
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\EventSubscriber\ReplicaDatabaseIgnoreSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* System subscriber for controller requests.
|
||||
*/
|
||||
class ReplicaDatabaseIgnoreSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Checks and disables the replica database server if appropriate.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* The Event to process.
|
||||
*/
|
||||
public function checkReplicaServer(GetResponseEvent $event) {
|
||||
// Ignore replica database servers for this request.
|
||||
//
|
||||
// In Drupal's distributed database structure, new data is written to the
|
||||
// master and then propagated to the replica servers. This means there is a
|
||||
// lag between when data is written to the master and when it is available
|
||||
// on the replica. At these times, we will want to avoid using a replica server
|
||||
// temporarily. For example, if a user posts a new node then we want to
|
||||
// disable the replica server for that user temporarily to allow the replica
|
||||
// server to catch up.
|
||||
// That way, that user will see their changes immediately while for other
|
||||
// users we still get the benefits of having a replica server, just with
|
||||
// slightly stale data. Code that wants to disable the replica server should
|
||||
// use the db_set_ignore_replica() function to set
|
||||
// $_SESSION['ignore_replica_server'] to the timestamp after which the replica
|
||||
// can be re-enabled.
|
||||
if (isset($_SESSION['ignore_replica_server'])) {
|
||||
if ($_SESSION['ignore_replica_server'] >= REQUEST_TIME) {
|
||||
Database::ignoreTarget('default', 'replica');
|
||||
}
|
||||
else {
|
||||
unset($_SESSION['ignore_replica_server']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static function getSubscribedEvents() {
|
||||
$events[KernelEvents::REQUEST][] = array('checkReplicaServer');
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\EventSubscriber\SlaveDatabaseIgnoreSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* System subscriber for controller requests.
|
||||
*/
|
||||
class SlaveDatabaseIgnoreSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Checks and disables the slave database server if appropriate.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* The Event to process.
|
||||
*/
|
||||
public function checkSlaveServer(GetResponseEvent $event) {
|
||||
// Ignore slave database servers for this request.
|
||||
//
|
||||
// In Drupal's distributed database structure, new data is written to the
|
||||
// master and then propagated to the slave servers. This means there is a
|
||||
// lag between when data is written to the master and when it is available
|
||||
// on the slave. At these times, we will want to avoid using a slave server
|
||||
// temporarily. For example, if a user posts a new node then we want to
|
||||
// disable the slave server for that user temporarily to allow the slave
|
||||
// server to catch up.
|
||||
// That way, that user will see their changes immediately while for other
|
||||
// users we still get the benefits of having a slave server, just with
|
||||
// slightly stale data. Code that wants to disable the slave server should
|
||||
// use the db_set_ignore_slave() function to set
|
||||
// $_SESSION['ignore_slave_server'] to the timestamp after which the slave
|
||||
// can be re-enabled.
|
||||
if (isset($_SESSION['ignore_slave_server'])) {
|
||||
if ($_SESSION['ignore_slave_server'] >= REQUEST_TIME) {
|
||||
Database::ignoreTarget('default', 'slave');
|
||||
}
|
||||
else {
|
||||
unset($_SESSION['ignore_slave_server']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static function getSubscribedEvents() {
|
||||
$events[KernelEvents::REQUEST][] = array('checkSlaveServer');
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -29,7 +29,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
|
|
|
@ -20,7 +20,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
|
|
|
@ -24,7 +24,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -95,8 +95,8 @@ class MenuLinkStorage extends EntityDatabaseStorage implements MenuLinkStorageIn
|
|||
}
|
||||
}
|
||||
|
||||
// Ignore slave server temporarily.
|
||||
db_ignore_slave();
|
||||
// Ignore replica server temporarily.
|
||||
db_ignore_replica();
|
||||
unset($entity->original);
|
||||
|
||||
return $return;
|
||||
|
|
|
@ -16,7 +16,7 @@ display:
|
|||
query_comment: false
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
title: 'Monthly archive'
|
||||
|
|
|
@ -24,7 +24,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -137,7 +137,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -16,7 +16,7 @@ display:
|
|||
query_comment: false
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
use_ajax: true
|
||||
|
|
|
@ -182,7 +182,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
|
||||
// Build matching conditions.
|
||||
$query = $this->database
|
||||
->select('search_index', 'i', array('target' => 'slave'))
|
||||
->select('search_index', 'i', array('target' => 'replica'))
|
||||
->extend('Drupal\search\SearchQuery')
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
|
||||
$query->join('node_field_data', 'n', 'n.nid = i.sid');
|
||||
|
@ -325,7 +325,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
// per cron run.
|
||||
$limit = (int) $this->searchSettings->get('index.cron_limit');
|
||||
|
||||
$result = $this->database->queryRange("SELECT n.nid, MAX(sd.reindex) FROM {node} n LEFT JOIN {search_dataset} sd ON sd.sid = n.nid AND sd.type = :type WHERE sd.sid IS NULL OR sd.reindex <> 0 GROUP BY n.nid ORDER BY MAX(sd.reindex) is null DESC, MAX(sd.reindex) ASC, n.nid ASC", 0, $limit, array(':type' => $this->getPluginId()), array('target' => 'slave'));
|
||||
$result = $this->database->queryRange("SELECT n.nid, MAX(sd.reindex) FROM {node} n LEFT JOIN {search_dataset} sd ON sd.sid = n.nid AND sd.type = :type WHERE sd.sid IS NULL OR sd.reindex <> 0 GROUP BY n.nid ORDER BY MAX(sd.reindex) is null DESC, MAX(sd.reindex) ASC, n.nid ASC", 0, $limit, array(':type' => $this->getPluginId()), array('target' => 'replica'));
|
||||
$nids = $result->fetchCol();
|
||||
if (!$nids) {
|
||||
return;
|
||||
|
|
|
@ -39,7 +39,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
row:
|
||||
|
|
|
@ -29,7 +29,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: '0'
|
||||
distinct: '0'
|
||||
slave: '0'
|
||||
replica: '0'
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
|
|
|
@ -222,7 +222,7 @@ function search_update_totals() {
|
|||
// Update word IDF (Inverse Document Frequency) counts for new/changed words.
|
||||
foreach (search_dirty() as $word => $dummy) {
|
||||
// Get total count
|
||||
$total = db_query("SELECT SUM(score) FROM {search_index} WHERE word = :word", array(':word' => $word), array('target' => 'slave'))->fetchField();
|
||||
$total = db_query("SELECT SUM(score) FROM {search_index} WHERE word = :word", array(':word' => $word), array('target' => 'replica'))->fetchField();
|
||||
// Apply Zipf's law to equalize the probability distribution.
|
||||
$total = log10(1 + 1/(max(1, $total)));
|
||||
db_merge('search_total')
|
||||
|
@ -233,7 +233,7 @@ function search_update_totals() {
|
|||
// Find words that were deleted from search_index, but are still in
|
||||
// search_total. We use a LEFT JOIN between the two tables and keep only the
|
||||
// rows which fail to join.
|
||||
$result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL", array(), array('target' => 'slave'));
|
||||
$result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL", array(), array('target' => 'replica'));
|
||||
$or = db_or();
|
||||
foreach ($result as $word) {
|
||||
$or->condition('word', $word->realword);
|
||||
|
|
|
@ -52,7 +52,7 @@ class Search extends ArgumentPluginBase {
|
|||
*/
|
||||
protected function queryParseSearchExpression($input) {
|
||||
if (!isset($this->searchQuery)) {
|
||||
$this->searchQuery = db_select('search_index', 'i', array('target' => 'slave'))->extend('Drupal\search\ViewsSearchQuery');
|
||||
$this->searchQuery = db_select('search_index', 'i', array('target' => 'replica'))->extend('Drupal\search\ViewsSearchQuery');
|
||||
$this->searchQuery->searchExpression($input, $this->searchType);
|
||||
$this->searchQuery->publicParseSearchExpression();
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ class Search extends FilterPluginBase {
|
|||
protected function queryParseSearchExpression($input) {
|
||||
if (!isset($this->searchQuery)) {
|
||||
$this->parsed = TRUE;
|
||||
$this->searchQuery = db_select('search_index', 'i', array('target' => 'slave'))->extend('Drupal\search\ViewsSearchQuery');
|
||||
$this->searchQuery = db_select('search_index', 'i', array('target' => 'replica'))->extend('Drupal\search\ViewsSearchQuery');
|
||||
$this->searchQuery->searchExpression($input, $this->searchType);
|
||||
$this->searchQuery->publicParseSearchExpression();
|
||||
}
|
||||
|
|
|
@ -600,7 +600,7 @@ class SearchQuery extends SelectExtender {
|
|||
$expressions = array();
|
||||
|
||||
// Add sid as the only field and count them as a subquery.
|
||||
$count = db_select($inner->fields('i', array('sid')), NULL, array('target' => 'slave'));
|
||||
$count = db_select($inner->fields('i', array('sid')), NULL, array('target' => 'replica'));
|
||||
|
||||
// Add the COUNT() expression.
|
||||
$count->addExpression('COUNT(*)');
|
||||
|
|
|
@ -155,7 +155,7 @@ function statistics_get($nid) {
|
|||
|
||||
if ($nid > 0) {
|
||||
// Retrieve an array with both totalcount and daycount.
|
||||
return db_query('SELECT totalcount, daycount, timestamp FROM {node_counter} WHERE nid = :nid', array(':nid' => $nid), array('target' => 'slave'))->fetchAssoc();
|
||||
return db_query('SELECT totalcount, daycount, timestamp FROM {node_counter} WHERE nid = :nid', array(':nid' => $nid), array('target' => 'replica'))->fetchAssoc();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,22 +26,22 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
* Tests that connections return appropriate connection objects.
|
||||
*/
|
||||
function testConnectionRouting() {
|
||||
// Clone the master credentials to a slave connection.
|
||||
// Clone the primary credentials to a replica connection.
|
||||
// Note this will result in two independent connection objects that happen
|
||||
// to point to the same place.
|
||||
$connection_info = Database::getConnectionInfo('default');
|
||||
Database::addConnectionInfo('default', 'slave', $connection_info['default']);
|
||||
Database::addConnectionInfo('default', 'replica', $connection_info['default']);
|
||||
|
||||
$db1 = Database::getConnection('default', 'default');
|
||||
$db2 = Database::getConnection('slave', 'default');
|
||||
$db2 = Database::getConnection('replica', 'default');
|
||||
|
||||
$this->assertNotNull($db1, 'default connection is a real connection object.');
|
||||
$this->assertNotNull($db2, 'slave connection is a real connection object.');
|
||||
$this->assertNotNull($db2, 'replica connection is a real connection object.');
|
||||
$this->assertNotIdentical($db1, $db2, 'Each target refers to a different connection.');
|
||||
|
||||
// Try to open those targets another time, that should return the same objects.
|
||||
$db1b = Database::getConnection('default', 'default');
|
||||
$db2b = Database::getConnection('slave', 'default');
|
||||
$db2b = Database::getConnection('replica', 'default');
|
||||
$this->assertIdentical($db1, $db1b, 'A second call to getConnection() returns the same object.');
|
||||
$this->assertIdentical($db2, $db2b, 'A second call to getConnection() returns the same object.');
|
||||
|
||||
|
@ -60,16 +60,16 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
* Tests that connections return appropriate connection objects.
|
||||
*/
|
||||
function testConnectionRoutingOverride() {
|
||||
// Clone the master credentials to a slave connection.
|
||||
// Clone the primary credentials to a replica connection.
|
||||
// Note this will result in two independent connection objects that happen
|
||||
// to point to the same place.
|
||||
$connection_info = Database::getConnectionInfo('default');
|
||||
Database::addConnectionInfo('default', 'slave', $connection_info['default']);
|
||||
Database::addConnectionInfo('default', 'replica', $connection_info['default']);
|
||||
|
||||
Database::ignoreTarget('default', 'slave');
|
||||
Database::ignoreTarget('default', 'replica');
|
||||
|
||||
$db1 = Database::getConnection('default', 'default');
|
||||
$db2 = Database::getConnection('slave', 'default');
|
||||
$db2 = Database::getConnection('replica', 'default');
|
||||
|
||||
$this->assertIdentical($db1, $db2, 'Both targets refer to the same connection.');
|
||||
}
|
||||
|
@ -104,14 +104,14 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
$this->assertEqual($connection_info['default']['driver'], $connectionOptions['driver'], 'The default connection info driver matches the current connection options driver.');
|
||||
$this->assertEqual($connection_info['default']['database'], $connectionOptions['database'], 'The default connection info database matches the current connection options database.');
|
||||
|
||||
// Set up identical slave and confirm connection options are identical.
|
||||
Database::addConnectionInfo('default', 'slave', $connection_info['default']);
|
||||
$db2 = Database::getConnection('slave', 'default');
|
||||
// Set up identical replica and confirm connection options are identical.
|
||||
Database::addConnectionInfo('default', 'replica', $connection_info['default']);
|
||||
$db2 = Database::getConnection('replica', 'default');
|
||||
$connectionOptions2 = $db2->getConnectionOptions();
|
||||
|
||||
// Get a fresh copy of the default connection options.
|
||||
$connectionOptions = $db->getConnectionOptions();
|
||||
$this->assertIdentical($connectionOptions, $connectionOptions2, 'The default and slave connection options are identical.');
|
||||
$this->assertIdentical($connectionOptions, $connectionOptions2, 'The default and replica connection options are identical.');
|
||||
|
||||
// Set up a new connection with different connection info.
|
||||
$test = $connection_info['default'];
|
||||
|
|
|
@ -66,22 +66,22 @@ class LoggingTest extends DatabaseTestBase {
|
|||
* Tests logging queries against multiple targets on the same connection.
|
||||
*/
|
||||
function testEnableTargetLogging() {
|
||||
// Clone the master credentials to a slave connection and to another fake
|
||||
// Clone the primary credentials to a replica connection and to another fake
|
||||
// connection.
|
||||
$connection_info = Database::getConnectionInfo('default');
|
||||
Database::addConnectionInfo('default', 'slave', $connection_info['default']);
|
||||
Database::addConnectionInfo('default', 'replica', $connection_info['default']);
|
||||
|
||||
Database::startLog('testing1');
|
||||
|
||||
db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol();
|
||||
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'slave'));//->fetchCol();
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'replica'));//->fetchCol();
|
||||
|
||||
$queries1 = Database::getLog('testing1');
|
||||
|
||||
$this->assertEqual(count($queries1), 2, 'Recorded queries from all targets.');
|
||||
$this->assertEqual($queries1[0]['target'], 'default', 'First query used default target.');
|
||||
$this->assertEqual($queries1[1]['target'], 'slave', 'Second query used slave target.');
|
||||
$this->assertEqual($queries1[1]['target'], 'replica', 'Second query used replica target.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,7 +98,7 @@ class LoggingTest extends DatabaseTestBase {
|
|||
|
||||
// We use "fake" here as a target because any non-existent target will do.
|
||||
// However, because all of the tests in this class share a single page
|
||||
// request there is likely to be a target of "slave" from one of the other
|
||||
// request there is likely to be a target of "replica" from one of the other
|
||||
// unit tests, so we use a target here that we know with absolute certainty
|
||||
// does not exist.
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'fake'))->fetchCol();
|
||||
|
@ -114,7 +114,7 @@ class LoggingTest extends DatabaseTestBase {
|
|||
* Tests that we can log queries separately on different connections.
|
||||
*/
|
||||
function testEnableMultiConnectionLogging() {
|
||||
// Clone the master credentials to a fake connection.
|
||||
// Clone the primary credentials to a fake connection.
|
||||
// That both connections point to the same physical database is irrelevant.
|
||||
$connection_info = Database::getConnectionInfo('default');
|
||||
Database::addConnectionInfo('test2', 'default', $connection_info['default']);
|
||||
|
@ -126,7 +126,7 @@ class LoggingTest extends DatabaseTestBase {
|
|||
|
||||
$old_key = db_set_active('test2');
|
||||
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'slave'))->fetchCol();
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'replica'))->fetchCol();
|
||||
|
||||
db_set_active($old_key);
|
||||
|
||||
|
|
|
@ -337,7 +337,7 @@ class SelectComplexTest extends DatabaseTestBase {
|
|||
'mail' => $this->randomName() . '@example.com',
|
||||
));
|
||||
|
||||
$query = db_select('test_task', 'tt', array('target' => 'slave'));
|
||||
$query = db_select('test_task', 'tt', array('target' => 'replica'));
|
||||
$query->addExpression('tt.pid + 1', 'abc');
|
||||
$query->condition('priority', 1, '>');
|
||||
$query->condition('priority', 100, '<');
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Contains \Drupal\system\Tests\System\IgnoreReplicaSubscriberTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\System;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\EventSubscriber\ReplicaDatabaseIgnoreSubscriber;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\simpletest\UnitTestBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
|
||||
/**
|
||||
* Tests the event subscriber that disables the replica database.
|
||||
*/
|
||||
class IgnoreSecondarySubscriberTest extends UnitTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Replica database ignoring event listener',
|
||||
'description' => 'Tests that ReplicaDatabaseIgnoreSubscriber functions correctly.',
|
||||
'group' => 'System',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\EventSubscriber\ReplicaDatabaseIgnoreSubscriber::checkReplicaServer().
|
||||
*/
|
||||
function testSystemInitIgnoresSecondaries() {
|
||||
// Clone the master credentials to a replica connection.
|
||||
// Note this will result in two independent connection objects that happen
|
||||
// to point to the same place.
|
||||
$connection_info = Database::getConnectionInfo('default');
|
||||
Database::addConnectionInfo('default', 'replica', $connection_info['default']);
|
||||
|
||||
db_ignore_replica();
|
||||
$kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
|
||||
$event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST);
|
||||
$subscriber = new ReplicaDatabaseIgnoreSubscriber();
|
||||
$subscriber->checkReplicaServer($event);
|
||||
|
||||
$db1 = Database::getConnection('default', 'default');
|
||||
$db2 = Database::getConnection('replica', 'default');
|
||||
|
||||
$this->assertIdentical($db1, $db2, 'System Init ignores secondaries when requested.');
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Contains \Drupal\system\Tests\System\IgnoreSlaveSubscriberTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\System;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\EventSubscriber\SlaveDatabaseIgnoreSubscriber;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\simpletest\UnitTestBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
|
||||
/**
|
||||
* Tests the event subscriber that disables the slave database.
|
||||
*/
|
||||
class IgnoreSlaveSubscriberTest extends UnitTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Slave database ignoring event listener',
|
||||
'description' => 'Tests that SlaveDatabaseIgnoreSubscriber functions correctly.',
|
||||
'group' => 'System',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\EventSubscriber\SlaveDatabaseIgnoreSubscriber::checkSlaveServer().
|
||||
*/
|
||||
function testSystemInitIgnoresSlaves() {
|
||||
// Clone the master credentials to a slave connection.
|
||||
// Note this will result in two independent connection objects that happen
|
||||
// to point to the same place.
|
||||
$connection_info = Database::getConnectionInfo('default');
|
||||
Database::addConnectionInfo('default', 'slave', $connection_info['default']);
|
||||
|
||||
db_ignore_slave();
|
||||
$kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
|
||||
$event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST);
|
||||
$subscriber = new SlaveDatabaseIgnoreSubscriber();
|
||||
$subscriber->checkSlaveServer($event);
|
||||
|
||||
$db1 = Database::getConnection('default', 'default');
|
||||
$db2 = Database::getConnection('slave', 'default');
|
||||
|
||||
$this->assertIdentical($db1, $db2, 'System Init ignores slaves when requested.');
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ display:
|
|||
query_comment: false
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
access:
|
||||
|
|
|
@ -22,7 +22,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
|
|
|
@ -25,7 +25,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -46,7 +46,7 @@ function tracker_cron() {
|
|||
$last_nid = FALSE;
|
||||
// @todo This should be actually filtering on the desired language and just
|
||||
// fall back to the default language.
|
||||
$result = db_query_range('SELECT nid, uid, status FROM {node_field_data} WHERE nid <= :max_nid AND default_langcode = 1 ORDER BY nid DESC', 0, $batch_size, array(':max_nid' => $max_nid), array('target' => 'slave'));
|
||||
$result = db_query_range('SELECT nid, uid, status FROM {node_field_data} WHERE nid <= :max_nid AND default_langcode = 1 ORDER BY nid DESC', 0, $batch_size, array(':max_nid' => $max_nid), array('target' => 'replica'));
|
||||
|
||||
$count = 0;
|
||||
|
||||
|
@ -81,7 +81,7 @@ function tracker_cron() {
|
|||
))
|
||||
->execute();
|
||||
|
||||
$query = db_select('comment', 'c', array('target' => 'slave'));
|
||||
$query = db_select('comment', 'c', array('target' => 'replica'));
|
||||
// Force PostgreSQL to do an implicit cast by adding 0.
|
||||
$query->addExpression('0 + :changed', 'changed', array(':changed' => $changed));
|
||||
$query->addField('c', 'status', 'published');
|
||||
|
@ -290,11 +290,11 @@ function _tracker_add($nid, $uid, $changed) {
|
|||
function _tracker_calculate_changed($nid) {
|
||||
// @todo This should be actually filtering on the desired language and just
|
||||
// fall back to the default language.
|
||||
$changed = db_query('SELECT changed FROM {node_field_data} WHERE nid = :nid AND default_langcode = 1 ORDER BY changed DESC', array(':nid' => $nid), array('target' => 'slave'))->fetchField();
|
||||
$changed = db_query('SELECT changed FROM {node_field_data} WHERE nid = :nid AND default_langcode = 1 ORDER BY changed DESC', array(':nid' => $nid), array('target' => 'replica'))->fetchField();
|
||||
$latest_comment = db_query_range("SELECT cid, changed FROM {comment} WHERE entity_type = 'node' AND entity_id = :nid AND status = :status ORDER BY changed DESC", 0, 1, array(
|
||||
':nid' => $nid,
|
||||
':status' => CommentInterface::PUBLISHED,
|
||||
), array('target' => 'slave'))->fetchObject();
|
||||
), array('target' => 'replica'))->fetchObject();
|
||||
if ($latest_comment && $latest_comment->changed > $changed) {
|
||||
$changed = $latest_comment->changed;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ function tracker_page($account = NULL) {
|
|||
->condition('t.uid', $account->id());
|
||||
}
|
||||
else {
|
||||
$query = db_select('tracker_node', 't', array('target' => 'slave'))
|
||||
$query = db_select('tracker_node', 't', array('target' => 'replica'))
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
|
||||
->addMetaData('base_table', 'tracker_node');
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ function tracker_page($account = NULL) {
|
|||
GROUP BY n.nid
|
||||
ORDER BY n.changed DESC", array(
|
||||
':nids' => array_keys($nodes)
|
||||
), array('target' => 'slave'))->fetchAllKeyed();
|
||||
), array('target' => 'replica'))->fetchAllKeyed();
|
||||
foreach ($result as $nid => $comment_count) {
|
||||
$nodes[$nid]->last_activity = $tracker_data[$nid]->changed;
|
||||
$nodes[$nid]->comment_count = $comment_count;
|
||||
|
|
|
@ -23,7 +23,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -24,7 +24,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -24,7 +24,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
provider: views
|
||||
|
|
|
@ -832,9 +832,9 @@ views_query:
|
|||
distinct:
|
||||
type: boolean
|
||||
label: 'Distinct'
|
||||
slave:
|
||||
replica:
|
||||
type: boolean
|
||||
label: 'Use Slave Server'
|
||||
label: 'Use Replica Server'
|
||||
query_tags:
|
||||
type: sequence
|
||||
label: 'Query Tags'
|
||||
|
|
|
@ -181,7 +181,7 @@ class Sql extends QueryPluginBase {
|
|||
'default' => FALSE,
|
||||
'bool' => TRUE,
|
||||
);
|
||||
$options['slave'] = array(
|
||||
$options['replica'] = array(
|
||||
'default' => FALSE,
|
||||
'bool' => TRUE,
|
||||
);
|
||||
|
@ -214,11 +214,11 @@ class Sql extends QueryPluginBase {
|
|||
'#description' => t('This will make the view display only distinct items. If there are multiple identical items, each will be displayed only once. You can use this to try and remove duplicates from a view, though it does not always work. Note that this can slow queries down, so use it with caution.'),
|
||||
'#default_value' => !empty($this->options['distinct']),
|
||||
);
|
||||
$form['slave'] = array(
|
||||
$form['replica'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Use Slave Server'),
|
||||
'#description' => t('This will make the query attempt to connect to a slave server if available. If no slave server is defined or available, it will fall back to the default server.'),
|
||||
'#default_value' => !empty($this->options['slave']),
|
||||
'#title' => t('Use Secondary Server'),
|
||||
'#description' => t('This will make the query attempt to connect to a replica server if available. If no replica server is defined or available, it will fall back to the default server.'),
|
||||
'#default_value' => !empty($this->options['replica']),
|
||||
);
|
||||
$form['query_comment'] = array(
|
||||
'#type' => 'textfield',
|
||||
|
@ -1204,9 +1204,9 @@ class Sql extends QueryPluginBase {
|
|||
$key = $this->view->base_database;
|
||||
}
|
||||
|
||||
// Set the slave target if the slave option is set
|
||||
if (!empty($this->options['slave'])) {
|
||||
$target = 'slave';
|
||||
// Set the replica target if the replica option is set
|
||||
if (!empty($this->options['replica'])) {
|
||||
$target = 'replica';
|
||||
}
|
||||
|
||||
// Go ahead and build the query.
|
||||
|
|
|
@ -87,7 +87,7 @@ display:
|
|||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
slave: false
|
||||
replica: false
|
||||
query_comment: false
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
|
|
|
@ -98,22 +98,23 @@
|
|||
* For each database, you may optionally specify multiple "target" databases.
|
||||
* A target database allows Drupal to try to send certain queries to a
|
||||
* different database if it can but fall back to the default connection if not.
|
||||
* That is useful for master/slave replication, as Drupal may try to connect
|
||||
* to a slave server when appropriate and if one is not available will simply
|
||||
* fall back to the single master server.
|
||||
* That is useful for primary/replica replication, as Drupal may try to connect
|
||||
* to a replica server when appropriate and if one is not available will simply
|
||||
* fall back to the single primary server (The terms primary/replica are
|
||||
* traditionally referred to as master/slave in database server documentation).
|
||||
*
|
||||
* The general format for the $databases array is as follows:
|
||||
* @code
|
||||
* $databases['default']['default'] = $info_array;
|
||||
* $databases['default']['slave'][] = $info_array;
|
||||
* $databases['default']['slave'][] = $info_array;
|
||||
* $databases['default']['replica'][] = $info_array;
|
||||
* $databases['default']['replica'][] = $info_array;
|
||||
* $databases['extra']['default'] = $info_array;
|
||||
* @endcode
|
||||
*
|
||||
* In the above example, $info_array is an array of settings described above.
|
||||
* The first line sets a "default" database that has one master database
|
||||
* The first line sets a "default" database that has one primary database
|
||||
* (the second level default). The second and third lines create an array
|
||||
* of potential slave databases. Drupal will select one at random for a given
|
||||
* of potential replica databases. Drupal will select one at random for a given
|
||||
* request as needed. The fourth line creates a new database with a name of
|
||||
* "extra".
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue