Issue #2275877 by Mixologic, duellj, Les Lim, Xano, David Strauss: Replace master/slave terminology with primary/replica.

8.0.x
webchick 2014-06-13 19:31:56 -07:00
parent 7fdb267c9c
commit b1b3b2b886
44 changed files with 220 additions and 216 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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.
*

View File

@ -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) {

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -23,7 +23,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -29,7 +29,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
exposed_form:

View File

@ -20,7 +20,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:

View File

@ -24,7 +24,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -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;

View File

@ -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'

View File

@ -24,7 +24,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -137,7 +137,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -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

View File

@ -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;

View File

@ -39,7 +39,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: ''
query_tags: { }
row:

View File

@ -29,7 +29,7 @@ display:
options:
disable_sql_rewrite: '0'
distinct: '0'
slave: '0'
replica: '0'
query_comment: ''
query_tags: { }
exposed_form:

View File

@ -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);

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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(*)');

View File

@ -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();
}
}

View File

@ -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'];

View File

@ -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);

View File

@ -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, '<');

View File

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

View File

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

View File

@ -16,7 +16,7 @@ display:
query_comment: false
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_tags: { }
provider: views
access:

View File

@ -22,7 +22,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:

View File

@ -25,7 +25,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -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;
}

View File

@ -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;

View File

@ -23,7 +23,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -24,7 +24,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -24,7 +24,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
provider: views

View File

@ -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'

View File

@ -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.

View File

@ -87,7 +87,7 @@ display:
options:
disable_sql_rewrite: false
distinct: false
slave: false
replica: false
query_comment: false
query_tags: { }
exposed_form:

View File

@ -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".
*