rdbms: cleanup getServer() and connection parameter fields in Database
Make getServer() always return a string, as documented, even with new Database::NEW_UNCONNECTED handles that have yet to call open(). If the 'host' parameter to __construct() is ''/null, getServer() now returns 'localhost' instead of null. This avoids problems like fatal errors in calls to TransactionProfiler::recordConnection(). Use Database constants for "connectionParams" field keys for better static analysis. Also: * Add Database::getServerName() method that returns "readable" server names in the style of LoadBalancer::getServerName(). Note that the "hostName" field is already passed in from LoadBalancer. * Migrate most getServer() callers to getServerName() for easier debugging and more readable logging. * Also, normalize Database/LoadBalancer SPI logging context to use "db_server" and reduce logging code duplication in LoadBalancer. Bug: T277056 Change-Id: I00ed4049ebb45edab1ea07561c47e226a423ea3b
This commit is contained in:
parent
f413a6210b
commit
99d5d2e8cc
18 changed files with 244 additions and 181 deletions
|
|
@ -177,7 +177,7 @@ class LegacyLogger extends AbstractLogger {
|
|||
$context['sql'],
|
||||
$context['method'],
|
||||
$context['runtime'],
|
||||
$context['db_host']
|
||||
$context['db_server']
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -464,6 +464,10 @@ class DBConnRef implements IDatabase {
|
|||
return $this->__call( __FUNCTION__, func_get_args() );
|
||||
}
|
||||
|
||||
public function getServerName() {
|
||||
return $this->__call( __FUNCTION__, func_get_args() );
|
||||
}
|
||||
|
||||
public function addQuotes( $s ) {
|
||||
return $this->__call( __FUNCTION__, func_get_args() );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
protected $user;
|
||||
/** @var string|null Password used to establish the current connection */
|
||||
protected $password;
|
||||
/** @var string|null Readible name or host/IP of the database server */
|
||||
protected $serverName;
|
||||
/** @var bool Whether this PHP instance is for a CLI script */
|
||||
protected $cliMode;
|
||||
/** @var string Agent name for query profiling */
|
||||
|
|
@ -92,7 +94,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
protected $topologyRole;
|
||||
/** @var string|null Host (or address) of the root master server for the replication topology */
|
||||
protected $topologyRootMaster;
|
||||
/** @var array Parameters used by initConnection() to establish a connection */
|
||||
/** @var array<string,mixed> Connection parameters used by initConnection() and open() */
|
||||
protected $connectionParams;
|
||||
/** @var string[]|int[]|float[] SQL variables values to use for all new connections */
|
||||
protected $connectionVariables;
|
||||
|
|
@ -260,6 +262,19 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
self::DBO_DEBUG | self::DBO_NOBUFFER | self::DBO_TRX | self::DBO_DDLMODE
|
||||
);
|
||||
|
||||
/** Hostname or IP address to use on all connections */
|
||||
protected const CONN_HOST = 'host';
|
||||
/** Database server username to use on all connections */
|
||||
protected const CONN_USER = 'user';
|
||||
/** Database server password to use on all connections */
|
||||
protected const CONN_PASSWORD = 'password';
|
||||
/** Database name to use on initial connection */
|
||||
protected const CONN_INITIAL_DB = 'dbname';
|
||||
/** Schema name to use on initial connection */
|
||||
protected const CONN_INITIAL_SCHEMA = 'schema';
|
||||
/** Table prefix to use on initial connection */
|
||||
protected const CONN_INITIAL_TABLE_PREFIX = 'tablePrefix';
|
||||
|
||||
/**
|
||||
* @note exceptions for missing libraries/drivers should be thrown in initConnection()
|
||||
* @stable to call
|
||||
|
|
@ -267,20 +282,20 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
*/
|
||||
public function __construct( array $params ) {
|
||||
$this->connectionParams = [
|
||||
'host' => ( isset( $params['host'] ) && $params['host'] !== '' )
|
||||
self::CONN_HOST => ( isset( $params['host'] ) && $params['host'] !== '' )
|
||||
? $params['host']
|
||||
: null,
|
||||
'user' => ( isset( $params['user'] ) && $params['user'] !== '' )
|
||||
self::CONN_USER => ( isset( $params['user'] ) && $params['user'] !== '' )
|
||||
? $params['user']
|
||||
: null,
|
||||
'dbname' => ( isset( $params['dbname'] ) && $params['dbname'] !== '' )
|
||||
self::CONN_INITIAL_DB => ( isset( $params['dbname'] ) && $params['dbname'] !== '' )
|
||||
? $params['dbname']
|
||||
: null,
|
||||
'schema' => ( isset( $params['schema'] ) && $params['schema'] !== '' )
|
||||
self::CONN_INITIAL_SCHEMA => ( isset( $params['schema'] ) && $params['schema'] !== '' )
|
||||
? $params['schema']
|
||||
: null,
|
||||
'password' => is_string( $params['password'] ) ? $params['password'] : null,
|
||||
'tablePrefix' => (string)$params['tablePrefix']
|
||||
self::CONN_PASSWORD => is_string( $params['password'] ) ? $params['password'] : null,
|
||||
self::CONN_INITIAL_TABLE_PREFIX => (string)$params['tablePrefix']
|
||||
];
|
||||
|
||||
$this->lbInfo = $params['lbInfo'] ?? [];
|
||||
|
|
@ -290,8 +305,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
$this->flags = (int)$params['flags'];
|
||||
$this->cliMode = (bool)$params['cliMode'];
|
||||
$this->agent = (string)$params['agent'];
|
||||
$this->topologyRole = (string)$params['topologyRole'];
|
||||
$this->topologyRootMaster = (string)$params['topologicalMaster'];
|
||||
$this->serverName = $params['serverName'];
|
||||
$this->topologyRole = $params['topologyRole'];
|
||||
$this->topologyRootMaster = $params['topologicalMaster'];
|
||||
$this->nonNativeInsertSelectBatchSize = $params['nonNativeInsertSelectBatchSize'] ?? 10000;
|
||||
|
||||
$this->srvCache = $params['srvCache'];
|
||||
|
|
@ -339,27 +355,27 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
*/
|
||||
protected function doInitConnection() {
|
||||
$this->open(
|
||||
$this->connectionParams['host'],
|
||||
$this->connectionParams['user'],
|
||||
$this->connectionParams['password'],
|
||||
$this->connectionParams['dbname'],
|
||||
$this->connectionParams['schema'],
|
||||
$this->connectionParams['tablePrefix']
|
||||
$this->connectionParams[self::CONN_HOST],
|
||||
$this->connectionParams[self::CONN_USER],
|
||||
$this->connectionParams[self::CONN_PASSWORD],
|
||||
$this->connectionParams[self::CONN_INITIAL_DB],
|
||||
$this->connectionParams[self::CONN_INITIAL_SCHEMA],
|
||||
$this->connectionParams[self::CONN_INITIAL_TABLE_PREFIX]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a new connection to the database (closing any existing one)
|
||||
*
|
||||
* @param string|null $server Database server host
|
||||
* @param string|null $user Database user name
|
||||
* @param string|null $password Database user password
|
||||
* @param string|null $dbName Database name
|
||||
* @param string|null $server Server host/address and optional port {@see connectionParams}
|
||||
* @param string|null $user User name {@see connectionParams}
|
||||
* @param string|null $password User password {@see connectionParams}
|
||||
* @param string|null $db Database name
|
||||
* @param string|null $schema Database schema name
|
||||
* @param string $tablePrefix Table prefix
|
||||
* @throws DBConnectionError
|
||||
*/
|
||||
abstract protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix );
|
||||
abstract protected function open( $server, $user, $password, $db, $schema, $tablePrefix );
|
||||
|
||||
/**
|
||||
* Construct a Database subclass instance given a database type and parameters
|
||||
|
|
@ -368,7 +384,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
*
|
||||
* @param string $type A possible DB type (sqlite, mysql, postgres,...)
|
||||
* @param array $params Parameter map with keys:
|
||||
* - host : The hostname of the DB server
|
||||
* - host : The hostname or IP address of the database server
|
||||
* - user : The name of the database user the client operates under
|
||||
* - password : The password for the database user
|
||||
* - dbname : The name of the database to use where queries do not specify one.
|
||||
|
|
@ -388,7 +404,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
* 'mysqli' driver; the old one 'mysql' has been removed.
|
||||
* - variables: Optional map of session variables to set after connecting. This can be
|
||||
* used to adjust lock timeouts or encoding modes and the like.
|
||||
* - topologyRole: Optional IDatabase::ROLE_* constant for the server.
|
||||
* - serverName : Optional readable name for the database server.
|
||||
* - topologyRole: Optional IDatabase::ROLE_* constant for the database server.
|
||||
* - topologicalMaster: Optional name of the master server within the replication topology.
|
||||
* - lbInfo: Optional map of field/values for the managing load balancer instance.
|
||||
* The "master" and "replica" fields are used to flag the replication role of this
|
||||
|
|
@ -433,6 +450,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
'cliMode' => ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ),
|
||||
'agent' => '',
|
||||
'ownerId' => null,
|
||||
'serverName' => null,
|
||||
'topologyRole' => null,
|
||||
'topologicalMaster' => null,
|
||||
// Objects and callbacks
|
||||
|
|
@ -919,9 +937,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
protected function getLogContext( array $extras = [] ) {
|
||||
return array_merge(
|
||||
[
|
||||
'db_server' => $this->server,
|
||||
'db_server' => $this->getServerName(),
|
||||
'db_name' => $this->getDBname(),
|
||||
'db_user' => $this->user,
|
||||
'db_user' => $this->connectionParams[self::CONN_USER],
|
||||
],
|
||||
$extras
|
||||
);
|
||||
|
|
@ -1394,7 +1412,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
if ( $this->trxLevel() && !$this->trxDoneWrites ) {
|
||||
$this->trxDoneWrites = true;
|
||||
$this->trxProfiler->transactionWritingIn(
|
||||
$this->getServer(),
|
||||
$this->getServerName(),
|
||||
$this->getDomainID(),
|
||||
$this->trxShortId
|
||||
);
|
||||
|
|
@ -1452,14 +1470,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
// Avoid the overhead of logging calls unless debug mode is enabled
|
||||
if ( $this->getFlag( self::DBO_DEBUG ) ) {
|
||||
$this->queryLogger->debug(
|
||||
"{method} [{runtime}s] {db_host}: {sql}",
|
||||
[
|
||||
"{method} [{runtime}s] {db_server}: {sql}",
|
||||
$this->getLogContext( [
|
||||
'method' => $fname,
|
||||
'db_host' => $this->getServer(),
|
||||
'sql' => $sql,
|
||||
'domain' => $this->getDomainID(),
|
||||
'runtime' => round( $queryRuntime, 3 )
|
||||
]
|
||||
] )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1624,7 +1641,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
// @note: leave trxRecurringCallbacks in place
|
||||
if ( $this->trxDoneWrites ) {
|
||||
$this->trxProfiler->transactionWritingOut(
|
||||
$this->getServer(),
|
||||
$this->getServerName(),
|
||||
$this->getDomainID(),
|
||||
$oldTrxShortId,
|
||||
$this->pendingWriteQueryDuration( self::ESTIMATE_TOTAL ),
|
||||
|
|
@ -2847,7 +2864,11 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
}
|
||||
|
||||
public function getServer() {
|
||||
return $this->server;
|
||||
return $this->connectionParams[self::CONN_HOST] ?? null;
|
||||
}
|
||||
|
||||
public function getServerName() {
|
||||
return $this->serverName ?? $this->getServer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4769,7 +4790,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
if ( $this->trxDoneWrites ) {
|
||||
$this->lastWriteTime = microtime( true );
|
||||
$this->trxProfiler->transactionWritingOut(
|
||||
$this->getServer(),
|
||||
$this->getServerName(),
|
||||
$this->getDomainID(),
|
||||
$oldTrxShortId,
|
||||
$writeTime,
|
||||
|
|
@ -4833,7 +4854,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
$writeTime = $this->pingAndCalculateLastTrxApplyTime();
|
||||
if ( $this->trxDoneWrites ) {
|
||||
$this->trxProfiler->transactionWritingOut(
|
||||
$this->getServer(),
|
||||
$this->getServerName(),
|
||||
$this->getDomainID(),
|
||||
$oldTrxShortId,
|
||||
$writeTime,
|
||||
|
|
@ -5015,9 +5036,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
|
||||
try {
|
||||
$this->open(
|
||||
$this->server,
|
||||
$this->user,
|
||||
$this->password,
|
||||
$this->connectionParams[self::CONN_HOST],
|
||||
$this->connectionParams[self::CONN_USER],
|
||||
$this->connectionParams[self::CONN_PASSWORD],
|
||||
$this->currentDomain->getDatabase(),
|
||||
$this->currentDomain->getSchema(),
|
||||
$this->tablePrefix()
|
||||
|
|
@ -5026,18 +5047,15 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
$ok = true;
|
||||
|
||||
$this->connLogger->warning(
|
||||
$fname . ': lost connection to {dbserver}; reconnected',
|
||||
[
|
||||
'dbserver' => $this->getServer(),
|
||||
'exception' => new RuntimeException()
|
||||
]
|
||||
$fname . ': lost connection to {db_server}; reconnected',
|
||||
$this->getLogContext( [ 'exception' => new RuntimeException() ] )
|
||||
);
|
||||
} catch ( DBConnectionError $e ) {
|
||||
$ok = false;
|
||||
|
||||
$this->connLogger->error(
|
||||
$fname . ': lost connection to {dbserver} permanently',
|
||||
[ 'dbserver' => $this->getServer() ]
|
||||
$fname . ': lost connection to {db_server} permanently',
|
||||
$this->getLogContext( [ 'exception' => new RuntimeException() ] )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -5150,6 +5168,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
*
|
||||
* Callers should avoid using this method while a transaction is active
|
||||
*
|
||||
* @see getLag()
|
||||
*
|
||||
* @stable to override
|
||||
* @return float|int|false Database replication lag in seconds or false on error
|
||||
* @throws DBError
|
||||
|
|
@ -5835,9 +5855,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
$this->trxSectionCancelCallbacks = []; // don't copy
|
||||
$this->handleSessionLossPreconnect(); // no trx or locks anymore
|
||||
$this->open(
|
||||
$this->server,
|
||||
$this->user,
|
||||
$this->password,
|
||||
$this->connectionParams[self::CONN_HOST],
|
||||
$this->connectionParams[self::CONN_USER],
|
||||
$this->connectionParams[self::CONN_PASSWORD],
|
||||
$this->currentDomain->getDatabase(),
|
||||
$this->currentDomain->getSchema(),
|
||||
$this->tablePrefix()
|
||||
|
|
|
|||
|
|
@ -52,7 +52,11 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
protected $sslCAFile;
|
||||
/** @var string|null */
|
||||
protected $sslCAPath;
|
||||
/** @var string[]|null */
|
||||
/**
|
||||
* Open SSL cipher list string
|
||||
* @see https://www.openssl.org/docs/man1.0.2/man1/ciphers.html
|
||||
* @var string|null
|
||||
*/
|
||||
protected $sslCiphers;
|
||||
/** @var string sql_mode value to send on connection */
|
||||
protected $sqlMode;
|
||||
|
|
@ -116,20 +120,16 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
return 'mysql';
|
||||
}
|
||||
|
||||
protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
|
||||
protected function open( $server, $user, $password, $db, $schema, $tablePrefix ) {
|
||||
$this->close( __METHOD__ );
|
||||
|
||||
if ( $schema !== null ) {
|
||||
throw $this->newExceptionAfterConnectError( "Got schema '$schema'; not supported." );
|
||||
}
|
||||
|
||||
$this->server = $server;
|
||||
$this->user = $user;
|
||||
$this->password = $password;
|
||||
|
||||
$this->installErrorHandler();
|
||||
try {
|
||||
$this->conn = $this->mysqlConnect( $this->server, $dbName );
|
||||
$this->conn = $this->mysqlConnect( $server, $user, $password, $db );
|
||||
} catch ( RuntimeException $e ) {
|
||||
$this->restoreErrorHandler();
|
||||
throw $this->newExceptionAfterConnectError( $e->getMessage() );
|
||||
|
|
@ -142,7 +142,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
|
||||
try {
|
||||
$this->currentDomain = new DatabaseDomain(
|
||||
strlen( $dbName ) ? $dbName : null,
|
||||
strlen( $db ) ? $db : null,
|
||||
null,
|
||||
$tablePrefix
|
||||
);
|
||||
|
|
@ -216,12 +216,14 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
/**
|
||||
* Open a connection to a MySQL server
|
||||
*
|
||||
* @param string $realServer
|
||||
* @param string|null $dbName
|
||||
* @param string|null $server
|
||||
* @param string|null $user
|
||||
* @param string|null $password
|
||||
* @param string|null $db
|
||||
* @return mixed|null Driver connection handle
|
||||
* @throws DBConnectionError
|
||||
*/
|
||||
abstract protected function mysqlConnect( $realServer, $dbName );
|
||||
abstract protected function mysqlConnect( $server, $user, $password, $db );
|
||||
|
||||
/**
|
||||
* @param IResultWrapper|resource $res
|
||||
|
|
@ -427,7 +429,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
$error = $this->mysqlError();
|
||||
}
|
||||
if ( $error ) {
|
||||
$error .= ' (' . $this->server . ')';
|
||||
$error .= ' (' . $this->getServerName() . ')';
|
||||
}
|
||||
|
||||
return $error;
|
||||
|
|
@ -766,7 +768,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
'mysql',
|
||||
'master-info',
|
||||
// Using one key for all cluster replica DBs is preferable
|
||||
$this->topologyRootMaster ?? $this->getServer()
|
||||
$this->topologyRootMaster ?? $this->getServerName()
|
||||
);
|
||||
$fname = __METHOD__;
|
||||
|
||||
|
|
@ -828,7 +830,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
return parent::getApproximateLagStatus();
|
||||
}
|
||||
|
||||
$key = $this->srvCache->makeGlobalKey( 'mysql-lag', $this->getServer() );
|
||||
$key = $this->srvCache->makeGlobalKey( 'mysql-lag', $this->getServerName() );
|
||||
$approxLag = $this->srvCache->get( $key );
|
||||
if ( !$approxLag ) {
|
||||
$approxLag = parent::getApproximateLagStatus();
|
||||
|
|
@ -1027,7 +1029,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
protected function getServerId() {
|
||||
$fname = __METHOD__;
|
||||
return $this->srvCache->getWithSetCallback(
|
||||
$this->srvCache->makeGlobalKey( 'mysql-server-id', $this->getServer() ),
|
||||
$this->srvCache->makeGlobalKey( 'mysql-server-id', $this->getServerName() ),
|
||||
self::SERVER_ID_CACHE_TTL,
|
||||
function () use ( $fname ) {
|
||||
$flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE;
|
||||
|
|
@ -1044,7 +1046,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
protected function getServerUUID() {
|
||||
$fname = __METHOD__;
|
||||
return $this->srvCache->getWithSetCallback(
|
||||
$this->srvCache->makeGlobalKey( 'mysql-server-uuid', $this->getServer() ),
|
||||
$this->srvCache->makeGlobalKey( 'mysql-server-uuid', $this->getServerName() ),
|
||||
self::SERVER_ID_CACHE_TTL,
|
||||
function () use ( $fname ) {
|
||||
$flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE;
|
||||
|
|
@ -1142,7 +1144,7 @@ abstract class DatabaseMysqlBase extends Database {
|
|||
$fname = __METHOD__;
|
||||
|
||||
return $cache->getWithSetCallback(
|
||||
$cache->makeGlobalKey( 'mysql-server-version', $this->getServer() ),
|
||||
$cache->makeGlobalKey( 'mysql-server-version', $this->getServerName() ),
|
||||
$cache::TTL_HOUR,
|
||||
function () use ( $fname ) {
|
||||
// Not using mysql_get_server_info() or similar for consistency: in the handshake,
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@ class DatabaseMysqli extends DatabaseMysqlBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $realServer
|
||||
* @param string|null $dbName
|
||||
* @param string|null $server
|
||||
* @param string|null $user
|
||||
* @param string|null $password
|
||||
* @param string|null $db
|
||||
* @return mysqli|null
|
||||
* @throws DBConnectionError
|
||||
*/
|
||||
protected function mysqlConnect( $realServer, $dbName ) {
|
||||
protected function mysqlConnect( $server, $user, $password, $db ) {
|
||||
if ( !function_exists( 'mysqli_init' ) ) {
|
||||
throw $this->newExceptionAfterConnectError(
|
||||
"MySQLi functions missing, have you compiled PHP with the --with-mysqli option?"
|
||||
|
|
@ -72,25 +74,27 @@ class DatabaseMysqli extends DatabaseMysqlBase {
|
|||
// We need to parse the port or socket path out of $realServer
|
||||
$port = null;
|
||||
$socket = null;
|
||||
$hostAndPort = IPUtils::splitHostAndPort( $realServer );
|
||||
$hostAndPort = IPUtils::splitHostAndPort( $server );
|
||||
if ( $hostAndPort ) {
|
||||
$realServer = $hostAndPort[0];
|
||||
if ( $hostAndPort[1] ) {
|
||||
$port = $hostAndPort[1];
|
||||
}
|
||||
} elseif ( substr_count( $realServer, ':/' ) == 1 ) {
|
||||
} elseif ( substr_count( $server, ':/' ) == 1 ) {
|
||||
// If we have a colon slash instead of a colon and a port number
|
||||
// after the ip or hostname, assume it's the Unix domain socket path
|
||||
list( $realServer, $socket ) = explode( ':', $realServer, 2 );
|
||||
list( $realServer, $socket ) = explode( ':', $server, 2 );
|
||||
} else {
|
||||
$realServer = $server;
|
||||
}
|
||||
|
||||
$mysqli = mysqli_init();
|
||||
// Make affectedRows() for UPDATE reflect the number of matching rows, regardless
|
||||
// of whether any column values changed. This is what callers want to know and is
|
||||
// consistent with what Postgres, SQLite, and SQL Server return.
|
||||
$connFlags = MYSQLI_CLIENT_FOUND_ROWS;
|
||||
$flags = MYSQLI_CLIENT_FOUND_ROWS;
|
||||
if ( $this->getFlag( self::DBO_SSL ) ) {
|
||||
$connFlags |= MYSQLI_CLIENT_SSL;
|
||||
$flags |= MYSQLI_CLIENT_SSL;
|
||||
$mysqli->ssl_set(
|
||||
$this->sslKeyPath,
|
||||
$this->sslCertPath,
|
||||
|
|
@ -100,7 +104,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
|
|||
);
|
||||
}
|
||||
if ( $this->getFlag( self::DBO_COMPRESS ) ) {
|
||||
$connFlags |= MYSQLI_CLIENT_COMPRESS;
|
||||
$flags |= MYSQLI_CLIENT_COMPRESS;
|
||||
}
|
||||
if ( $this->getFlag( self::DBO_PERSISTENT ) ) {
|
||||
$realServer = 'p:' . $realServer;
|
||||
|
|
@ -115,19 +119,9 @@ class DatabaseMysqli extends DatabaseMysqlBase {
|
|||
}
|
||||
$mysqli->options( MYSQLI_OPT_CONNECT_TIMEOUT, 3 );
|
||||
|
||||
if ( $mysqli->real_connect(
|
||||
$realServer,
|
||||
$this->user,
|
||||
$this->password,
|
||||
$dbName,
|
||||
$port,
|
||||
$socket,
|
||||
$connFlags
|
||||
) ) {
|
||||
return $mysqli;
|
||||
}
|
||||
$ok = $mysqli->real_connect( $realServer, $user, $password, $db, $port, $socket, $flags );
|
||||
|
||||
return null;
|
||||
return $ok ? $mysqli : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ class DatabasePostgres extends Database {
|
|||
private $coreSchema;
|
||||
/** @var string */
|
||||
private $tempSchema;
|
||||
/** @var string[] Map of (reserved table name => alternate table name) */
|
||||
private $keywordTableMap = [];
|
||||
/** @var null|string[] Map of (reserved table name => alternate table name) */
|
||||
private $keywordTableMap;
|
||||
/** @var float|string */
|
||||
private $numericVersion;
|
||||
|
||||
|
|
@ -48,6 +48,7 @@ class DatabasePostgres extends Database {
|
|||
/**
|
||||
* @see Database::__construct()
|
||||
* @param array $params Additional parameters include:
|
||||
* - port: A port to append to the hostname
|
||||
* - keywordTableMap : Map of reserved table names to alternative table names to use
|
||||
* This is is deprecated since 1.37. Reserved identifiers should be quoted where necessary,
|
||||
*/
|
||||
|
|
@ -87,7 +88,7 @@ class DatabasePostgres extends Database {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
|
||||
protected function open( $server, $user, $password, $db, $schema, $tablePrefix ) {
|
||||
if ( !function_exists( 'pg_connect' ) ) {
|
||||
throw $this->newExceptionAfterConnectError(
|
||||
"Postgres functions missing, have you compiled PHP with the --with-pgsql\n" .
|
||||
|
|
@ -98,14 +99,10 @@ class DatabasePostgres extends Database {
|
|||
|
||||
$this->close( __METHOD__ );
|
||||
|
||||
$this->server = $server;
|
||||
$this->user = $user;
|
||||
$this->password = $password;
|
||||
|
||||
$connectVars = [
|
||||
// A database must be specified in order to connect to Postgres. If $dbName is not
|
||||
// specified, then use the standard "postgres" database that should exist by default.
|
||||
'dbname' => strlen( $dbName ) ? $dbName : 'postgres',
|
||||
'dbname' => strlen( $db ) ? $db : 'postgres',
|
||||
'user' => $user,
|
||||
'password' => $password
|
||||
];
|
||||
|
|
@ -153,7 +150,7 @@ class DatabasePostgres extends Database {
|
|||
);
|
||||
}
|
||||
$this->determineCoreSchema( $schema );
|
||||
$this->currentDomain = new DatabaseDomain( $dbName, $schema, $tablePrefix );
|
||||
$this->currentDomain = new DatabaseDomain( $db, $schema, $tablePrefix );
|
||||
} catch ( RuntimeException $e ) {
|
||||
throw $this->newExceptionAfterConnectError( $e->getMessage() );
|
||||
}
|
||||
|
|
@ -177,9 +174,9 @@ class DatabasePostgres extends Database {
|
|||
// Postgres doesn't support selectDB in the same way MySQL does.
|
||||
// So if the DB name doesn't match the open connection, open a new one
|
||||
$this->open(
|
||||
$this->server,
|
||||
$this->user,
|
||||
$this->password,
|
||||
$this->connectionParams[self::CONN_HOST],
|
||||
$this->connectionParams[self::CONN_USER],
|
||||
$this->connectionParams[self::CONN_PASSWORD],
|
||||
$domain->getDatabase(),
|
||||
$domain->getSchema(),
|
||||
$domain->getTablePrefix()
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ class DatabaseSqlite extends Database {
|
|||
return 'sqlite';
|
||||
}
|
||||
|
||||
protected function open( $server, $user, $pass, $dbName, $schema, $tablePrefix ) {
|
||||
protected function open( $server, $user, $password, $db, $schema, $tablePrefix ) {
|
||||
$this->close( __METHOD__ );
|
||||
|
||||
// Note that for SQLite, $server, $user, and $pass are ignored
|
||||
|
|
@ -145,7 +145,7 @@ class DatabaseSqlite extends Database {
|
|||
if ( $this->dbPath !== null ) {
|
||||
$path = $this->dbPath;
|
||||
} elseif ( $this->dbDir !== null ) {
|
||||
$path = self::generateFileName( $this->dbDir, $dbName );
|
||||
$path = self::generateFileName( $this->dbDir, $db );
|
||||
} else {
|
||||
throw $this->newExceptionAfterConnectError( "DB path or directory required" );
|
||||
}
|
||||
|
|
@ -161,8 +161,6 @@ class DatabaseSqlite extends Database {
|
|||
throw $this->newExceptionAfterConnectError( "Got mode '{$this->trxMode}' for BEGIN" );
|
||||
}
|
||||
|
||||
$this->server = 'localhost';
|
||||
|
||||
$attributes = [];
|
||||
if ( $this->getFlag( self::DBO_PERSISTENT ) ) {
|
||||
// Persistent connections can avoid some schema index reading overhead.
|
||||
|
|
@ -184,7 +182,7 @@ class DatabaseSqlite extends Database {
|
|||
throw $this->newExceptionAfterConnectError( $e->getMessage() );
|
||||
}
|
||||
|
||||
$this->currentDomain = new DatabaseDomain( $dbName, null, $tablePrefix );
|
||||
$this->currentDomain = new DatabaseDomain( $db, null, $tablePrefix );
|
||||
|
||||
try {
|
||||
$flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_NO_RETRY;
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ interface IDatabase {
|
|||
public function getDomainID();
|
||||
|
||||
/**
|
||||
* Get the type of the DBMS (e.g. "mysql", "sqlite")
|
||||
* Get the RDBMS type of the server (e.g. "mysql", "sqlite")
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -1217,17 +1217,27 @@ interface IDatabase {
|
|||
public function selectDomain( $domain );
|
||||
|
||||
/**
|
||||
* Get the current DB name
|
||||
* Get the current database name; null if there isn't one
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDBname();
|
||||
|
||||
/**
|
||||
* Get the server hostname or IP address
|
||||
* @return string
|
||||
* Get the hostname or IP address of the server
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getServer();
|
||||
|
||||
/**
|
||||
* Get the readable name for the server
|
||||
*
|
||||
* @return string Readable server name, falling back to the hostname or IP address
|
||||
* @since 1.36
|
||||
*/
|
||||
public function getServerName();
|
||||
|
||||
/**
|
||||
* Escape and quote a raw value string for use in a SQL query
|
||||
*
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class LBFactoryMulti extends LBFactory {
|
|||
/** @var LoadBalancer[] Map of (external cluster => tracked LoadBalancer) */
|
||||
private $externalLBs = [];
|
||||
|
||||
/** @var string[] Map of (hostname => IP address) */
|
||||
/** @var string[] Map of (server name => IP address) */
|
||||
private $hostsByServerName;
|
||||
/** @var string[] Map of (database name => main section) */
|
||||
private $sectionsByDB;
|
||||
|
|
@ -48,7 +48,7 @@ class LBFactoryMulti extends LBFactory {
|
|||
private $groupLoadsByDB;
|
||||
/** @var int[][] Map of (external cluster => server name => load ratio) */
|
||||
private $externalLoadsByCluster;
|
||||
/** @var array Server config map ("host", "hostName", "load", and "groupLoads" are ignored) */
|
||||
/** @var array Server config map ("host", "serverName", "load", and "groupLoads" ignored) */
|
||||
private $serverTemplate;
|
||||
/** @var array Server config map overriding "serverTemplate" for all external servers */
|
||||
private $externalTemplateOverrides;
|
||||
|
|
@ -82,7 +82,7 @@ class LBFactoryMulti extends LBFactory {
|
|||
*
|
||||
* @see LBFactory::__construct()
|
||||
* @param array $conf Additional parameters include:
|
||||
* - hostsByName: map of (hostname => IP address). [optional]
|
||||
* - hostsByName: map of (server name => IP address). [optional]
|
||||
* - sectionsByDB: map of (database => main section). The database name "DEFAULT" is
|
||||
* interpeted as a catch-all for all databases not otherwise mentioned. [optional]
|
||||
* - sectionLoads: map of (main section => server name => load ratio); the first host
|
||||
|
|
@ -92,7 +92,7 @@ class LBFactoryMulti extends LBFactory {
|
|||
* - groupLoadsByDB: map of (database => group => server name => load ratio) map. [optional]
|
||||
* - externalLoads: map of (cluster => server name => load ratio) map. [optional]
|
||||
* - serverTemplate: server config map for Database::factory().
|
||||
* Note that "host", "hostName" and "load" entries will be overridden by
|
||||
* Note that "host", "serverName" and "load" entries will be overridden by
|
||||
* "groupLoadsBySection" and "hostsByName". [optional]
|
||||
* - externalTemplateOverrides: server config map overrides for external stores;
|
||||
* respects the override precedence described above. [optional]
|
||||
|
|
@ -296,7 +296,7 @@ class LBFactoryMulti extends LBFactory {
|
|||
$this->templateOverridesByServer[$serverName] ?? [],
|
||||
[
|
||||
'host' => $this->hostsByServerName[$serverName] ?? $serverName,
|
||||
'hostName' => $serverName,
|
||||
'serverName' => $serverName,
|
||||
'load' => $load,
|
||||
'groupLoads' => $groupLoadsByServerName[$serverName] ?? []
|
||||
]
|
||||
|
|
|
|||
|
|
@ -477,31 +477,34 @@ interface ILoadBalancer {
|
|||
public function hasStreamingReplicaServers();
|
||||
|
||||
/**
|
||||
* Get the name of the server with the specified index
|
||||
* Get the readable name of the server with the specified index
|
||||
*
|
||||
* @param int $i
|
||||
* @return string Readable name if available or IP/host otherwise
|
||||
* @param int $i Specific server index
|
||||
* @return string Readable server name, falling back to the hostname or IP address
|
||||
*/
|
||||
public function getServerName( $i );
|
||||
|
||||
/**
|
||||
* Return the server info structure for a given index or false if the index is invalid.
|
||||
* @param int $i
|
||||
* @return array|bool
|
||||
* Return the server configuration map for the server with the specified index
|
||||
*
|
||||
* @param int $i Specific server index
|
||||
* @return array|false Server configuration map; false if the index is invalid
|
||||
* @since 1.31
|
||||
*/
|
||||
public function getServerInfo( $i );
|
||||
|
||||
/**
|
||||
* Get DB type of the server with the specified index
|
||||
* Get the RDBMS type of the server with the specified index (e.g. "mysql", "sqlite")
|
||||
*
|
||||
* @param int $i
|
||||
* @param int $i Specific server index
|
||||
* @return string One of (mysql,postgres,sqlite,...) or "unknown" for bad indexes
|
||||
* @since 1.30
|
||||
*/
|
||||
public function getServerType( $i );
|
||||
|
||||
/**
|
||||
* Get basic attributes of the server with the specified index without connecting
|
||||
*
|
||||
* @param int $i Specific server index
|
||||
* @return array (Database::ATTRIBUTE_* constant => value) for all such constants
|
||||
* @since 1.31
|
||||
|
|
|
|||
|
|
@ -234,9 +234,10 @@ class LoadBalancer implements ILoadBalancer {
|
|||
$this->deprecationLogger = $params['deprecationLogger'] ?? static function ( $msg ) {
|
||||
trigger_error( $msg, E_USER_DEPRECATED );
|
||||
};
|
||||
foreach ( [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ] as $key ) {
|
||||
$this->$key = $params[$key] ?? new NullLogger();
|
||||
}
|
||||
$this->replLogger = $params['replLogger'] ?? new NullLogger();
|
||||
$this->connLogger = $params['connLogger'] ?? new NullLogger();
|
||||
$this->queryLogger = $params['queryLogger'] ?? new NullLogger();
|
||||
$this->perfLogger = $params['perfLogger'] ?? new NullLogger();
|
||||
|
||||
$this->clusterName = $params['clusterName'] ?? null;
|
||||
$this->profiler = $params['profiler'] ?? null;
|
||||
|
|
@ -454,17 +455,18 @@ class LoadBalancer implements ILoadBalancer {
|
|||
# Constrain that futher by $maxLag argument
|
||||
$maxServerLag = min( $maxServerLag, $maxLag );
|
||||
|
||||
$host = $this->getServerName( $i );
|
||||
$srvName = $this->getServerName( $i );
|
||||
if ( $lag === false && !is_infinite( $maxServerLag ) ) {
|
||||
$this->replLogger->debug(
|
||||
__METHOD__ .
|
||||
": server {dbserver} is not replicating?", [ 'dbserver' => $host ] );
|
||||
__METHOD__ . ": server {db_server} is not replicating?",
|
||||
[ 'db_server' => $srvName ]
|
||||
);
|
||||
unset( $loads[$i] );
|
||||
} elseif ( $lag > $maxServerLag ) {
|
||||
$this->replLogger->debug(
|
||||
__METHOD__ .
|
||||
": server {dbserver} has {lag} seconds of lag (>= {maxlag})",
|
||||
[ 'dbserver' => $host, 'lag' => $lag, 'maxlag' => $maxServerLag ]
|
||||
": server {db_server} has {lag} seconds of lag (>= {maxlag})",
|
||||
[ 'db_server' => $srvName, 'lag' => $lag, 'maxlag' => $maxServerLag ]
|
||||
);
|
||||
unset( $loads[$i] );
|
||||
}
|
||||
|
|
@ -845,8 +847,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
if ( !$conn->isOpen() ) {
|
||||
$this->connLogger->warning(
|
||||
__METHOD__ .
|
||||
": pooled DB handle for {dbserver} (#$i) has no open connection.",
|
||||
[ 'dbserver' => $conn->getServer() ]
|
||||
": pooled DB handle for {db_server} (#$i) has no open connection.",
|
||||
$this->getConnLogContext( $conn )
|
||||
);
|
||||
|
||||
continue; // some sort of error occurred?
|
||||
|
|
@ -863,8 +865,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
// Some sort of bug left a transaction open
|
||||
$this->connLogger->warning(
|
||||
__METHOD__ .
|
||||
": pooled DB handle for {dbserver} (#$i) has a pending transaction.",
|
||||
[ 'dbserver' => $conn->getServer() ]
|
||||
": pooled DB handle for {db_server} (#$i) has a pending transaction.",
|
||||
$this->getConnLogContext( $conn )
|
||||
);
|
||||
|
||||
continue;
|
||||
|
|
@ -889,8 +891,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
$timeout = max( 1, intval( $timeout ?: $this->waitTimeout ) );
|
||||
|
||||
// Check if we already know that the DB has reached this point
|
||||
$server = $this->getServerName( $index );
|
||||
$key = $this->srvCache->makeGlobalKey( __CLASS__, 'last-known-pos', $server, 'v1' );
|
||||
$srvName = $this->getServerName( $index );
|
||||
$key = $this->srvCache->makeGlobalKey( __CLASS__, 'last-known-pos', $srvName, 'v1' );
|
||||
/** @var DBMasterPos $knownReachedPos */
|
||||
$knownReachedPos = $this->srvCache->get( $key );
|
||||
if (
|
||||
|
|
@ -899,8 +901,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
) {
|
||||
$this->replLogger->debug(
|
||||
__METHOD__ .
|
||||
": replica DB {dbserver} known to be caught up (pos >= $knownReachedPos).",
|
||||
[ 'dbserver' => $server ]
|
||||
": replica DB {db_server} known to be caught up (pos >= $knownReachedPos).",
|
||||
[ 'db_server' => $srvName ]
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
@ -917,8 +919,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
$conn = $this->getServerConnection( $index, self::DOMAIN_ANY, $flags );
|
||||
if ( !$conn ) {
|
||||
$this->replLogger->warning(
|
||||
__METHOD__ . ': failed to connect to {dbserver}',
|
||||
[ 'dbserver' => $server ]
|
||||
__METHOD__ . ': failed to connect to {db_server}',
|
||||
[ 'db_server' => $srvName ]
|
||||
);
|
||||
|
||||
return false;
|
||||
|
|
@ -930,8 +932,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
|
||||
$this->replLogger->info(
|
||||
__METHOD__ .
|
||||
': waiting for replica DB {dbserver} to catch up...',
|
||||
[ 'dbserver' => $server ]
|
||||
': waiting for replica DB {db_server} to catch up...',
|
||||
$this->getConnLogContext( $conn )
|
||||
);
|
||||
|
||||
$result = $conn->masterPosWait( $this->waitForPos, $timeout );
|
||||
|
|
@ -1003,7 +1005,7 @@ class LoadBalancer implements ILoadBalancer {
|
|||
// Profile any new connections caused by this method
|
||||
if ( $this->connectionCounter > $priorConnectionsMade ) {
|
||||
$this->trxProfiler->recordConnection(
|
||||
$conn->getServer(),
|
||||
$conn->getServerName(),
|
||||
$conn->getDBname(),
|
||||
self::fieldHasBit( $flags, self::CONN_INTENT_WRITABLE )
|
||||
);
|
||||
|
|
@ -1435,12 +1437,14 @@ class LoadBalancer implements ILoadBalancer {
|
|||
if ( $count >= self::CONN_HELD_WARN_THRESHOLD ) {
|
||||
$this->perfLogger->warning(
|
||||
__METHOD__ . ": {connections}+ connections made (master={masterdb})",
|
||||
[
|
||||
'connections' => $count,
|
||||
'dbserver' => $conn->getServer(),
|
||||
'masterdb' => $this->getMasterServerName(),
|
||||
'db_domain' => $domain->getId()
|
||||
]
|
||||
$this->getConnLogContext(
|
||||
$conn,
|
||||
[
|
||||
'connections' => $count,
|
||||
'masterdb' => $this->getMasterServerName(),
|
||||
'db_domain' => $domain->getId()
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1501,13 +1505,13 @@ class LoadBalancer implements ILoadBalancer {
|
|||
];
|
||||
|
||||
if ( $conn instanceof IDatabase ) {
|
||||
$context['db_server'] = $conn->getServer();
|
||||
$srvName = $conn->getServerName();
|
||||
$this->connLogger->warning(
|
||||
__METHOD__ . ": connection error: {last_error} ({db_server})",
|
||||
$context
|
||||
$this->getConnLogContext( $conn, $context )
|
||||
);
|
||||
$error = $conn->lastError() ?: $this->lastError;
|
||||
throw new DBConnectionError( $conn, "$error ({$context['db_server']})" );
|
||||
throw new DBConnectionError( $conn, "{$error} ($srvName)" );
|
||||
} else {
|
||||
// No last connection, probably due to all servers being too busy
|
||||
$this->connLogger->error(
|
||||
|
|
@ -1574,7 +1578,7 @@ class LoadBalancer implements ILoadBalancer {
|
|||
}
|
||||
|
||||
public function getServerName( $i ) {
|
||||
$name = $this->servers[$i]['hostName'] ?? ( $this->servers[$i]['host'] ?? '' );
|
||||
$name = $this->servers[$i]['serverName'] ?? ( $this->servers[$i]['host'] ?? '' );
|
||||
|
||||
return ( $name != '' ) ? $name : 'localhost';
|
||||
}
|
||||
|
|
@ -1646,8 +1650,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
$scope = ScopedCallback::newScopedIgnoreUserAbort();
|
||||
}
|
||||
$this->forEachOpenConnection( function ( IDatabase $conn ) use ( $fname ) {
|
||||
$host = $conn->getServer();
|
||||
$this->connLogger->debug( "$fname: closing connection to database '$host'." );
|
||||
$srvName = $conn->getServerName();
|
||||
$this->connLogger->debug( "$fname: closing connection to database '$srvName'." );
|
||||
$conn->close( $fname, $this->id );
|
||||
} );
|
||||
|
||||
|
|
@ -1665,7 +1669,7 @@ class LoadBalancer implements ILoadBalancer {
|
|||
throw new RuntimeException( 'Database handle is missing server index' );
|
||||
}
|
||||
|
||||
$host = $this->getServerName( $serverIndex );
|
||||
$srvName = $this->getServerName( $serverIndex );
|
||||
$domain = $conn->getDomainID();
|
||||
|
||||
$found = false;
|
||||
|
|
@ -1680,13 +1684,13 @@ class LoadBalancer implements ILoadBalancer {
|
|||
if ( !$found ) {
|
||||
$this->connLogger->warning(
|
||||
__METHOD__ .
|
||||
": got orphaned connection to database $serverIndex/$domain at '$host'."
|
||||
": got orphaned connection to database $serverIndex/$domain at '$srvName'."
|
||||
);
|
||||
}
|
||||
|
||||
$this->connLogger->debug(
|
||||
__METHOD__ .
|
||||
": closing connection to database $serverIndex/$domain at '$host'."
|
||||
": closing connection to database $serverIndex/$domain at '$srvName'."
|
||||
);
|
||||
|
||||
$conn->close( __METHOD__ );
|
||||
|
|
@ -1815,7 +1819,7 @@ class LoadBalancer implements ILoadBalancer {
|
|||
$conn->commit( $fname, $conn::FLUSHING_ALL_PEERS );
|
||||
} catch ( DBError $e ) {
|
||||
( $this->errorLogger )( $e );
|
||||
$failures[] = "{$conn->getServer()}: {$e->getMessage()}";
|
||||
$failures[] = "{$conn->getServerName()}: {$e->getMessage()}";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1882,11 +1886,10 @@ class LoadBalancer implements ILoadBalancer {
|
|||
$fnames = implode( ', ', $conn->pendingWriteAndCallbackCallers() );
|
||||
$this->queryLogger->warning(
|
||||
"$fname: found writes pending ($fnames).",
|
||||
[
|
||||
'db_server' => $conn->getServer(),
|
||||
'db_domain' => $conn->getDomainID(),
|
||||
'exception' => new RuntimeException()
|
||||
]
|
||||
$this->getConnLogContext(
|
||||
$conn,
|
||||
[ 'exception' => new RuntimeException() ]
|
||||
)
|
||||
);
|
||||
} elseif ( $conn->trxLevel() ) {
|
||||
// A callback from another handle read from this one and DBO_TRX is set,
|
||||
|
|
@ -2149,7 +2152,7 @@ class LoadBalancer implements ILoadBalancer {
|
|||
// Note that table prefixes are not related to server-side read-only mode
|
||||
$key = $this->srvCache->makeGlobalKey(
|
||||
'rdbms-server-readonly',
|
||||
$conn->getServer(),
|
||||
$conn->getServerName(),
|
||||
$conn->getDBname(),
|
||||
$conn->dbSchema()
|
||||
);
|
||||
|
|
@ -2383,12 +2386,8 @@ class LoadBalancer implements ILoadBalancer {
|
|||
} else {
|
||||
$ok = false; // something is misconfigured
|
||||
$this->replLogger->error(
|
||||
__METHOD__ . ': could not get master pos for {dbserver}',
|
||||
[
|
||||
'dbserver' => $conn->getServer(),
|
||||
'db_domain' => $conn->getDomainID(),
|
||||
'exception' => new RuntimeException(),
|
||||
]
|
||||
__METHOD__ . ': could not get master pos for {db_server}',
|
||||
$this->getConnLogContext( $conn, [ 'exception' => new RuntimeException() ] )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2514,6 +2513,23 @@ class LoadBalancer implements ILoadBalancer {
|
|||
return ( ( $flags & $bit ) === $bit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a log context to pass to PSR-3 logger functions.
|
||||
*
|
||||
* @param IDatabase $conn
|
||||
* @param array $extras Additional data to add to context
|
||||
* @return array
|
||||
*/
|
||||
protected function getConnLogContext( IDatabase $conn, array $extras = [] ) {
|
||||
return array_merge(
|
||||
[
|
||||
'db_server' => $conn->getServerName(),
|
||||
'db_domain' => $conn->getDomainID()
|
||||
],
|
||||
$extras
|
||||
);
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
// Avoid connection leaks for sanity
|
||||
$this->disable( __METHOD__, $this->ownerId );
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ class LoadMonitor implements ILoadMonitor {
|
|||
$this->replLogger->warning(
|
||||
"Server {dbserver} has {lag} seconds of lag (>= {maxlag})",
|
||||
[
|
||||
'dbserver' => $host,
|
||||
'db_server' => $host,
|
||||
'lag' => $lagTimes[$i],
|
||||
'maxlag' => $this->lagWarnThreshold
|
||||
]
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class MwSql extends Maintenance {
|
|||
|
||||
$db = $lb->getMaintenanceConnectionRef( $index, [], $wiki );
|
||||
if ( $replicaDB != '' && $db->getLBInfo( 'master' ) !== null ) {
|
||||
$this->fatalError( "The server selected ({$db->getServer()}) is not a replica DB." );
|
||||
$this->fatalError( "Server {$db->getServerName()} is not a replica DB." );
|
||||
}
|
||||
|
||||
if ( $index === DB_PRIMARY ) {
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiIntegrationTestCase {
|
|||
'topologyRole' => Database::ROLE_STREAMING_MASTER,
|
||||
'topologicalMaster' => null,
|
||||
'agent' => '',
|
||||
'serverName' => '*dummy*',
|
||||
'load' => 100,
|
||||
'srvCache' => new HashBagOStuff(),
|
||||
'profiler' => null,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class DatabaseTestHelper extends Database {
|
|||
'flags' => 0,
|
||||
'cliMode' => true,
|
||||
'agent' => '',
|
||||
'serverName' => null,
|
||||
'topologyRole' => null,
|
||||
'topologicalMaster' => null,
|
||||
'srvCache' => new HashBagOStuff(),
|
||||
|
|
@ -176,8 +177,7 @@ class DatabaseTestHelper extends Database {
|
|||
return 'test';
|
||||
}
|
||||
|
||||
public function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
|
||||
$this->server = 'localhost';
|
||||
public function open( $server, $user, $password, $db, $schema, $tablePrefix ) {
|
||||
$this->conn = (object)[ 'test' ];
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class LoadBalancerTest extends MediaWikiIntegrationTestCase {
|
|||
|
||||
return [
|
||||
'host' => $wgDBserver,
|
||||
'hostName' => 'testhost',
|
||||
'serverName' => 'testhost',
|
||||
'dbname' => $wgDBname,
|
||||
'tablePrefix' => $this->dbPrefix(),
|
||||
'user' => $wgDBuser,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class DatabaseSqliteTest extends \MediaWikiIntegrationTestCase {
|
|||
'tablePrefix' => '',
|
||||
'cliMode' => true,
|
||||
'agent' => 'unit-tests',
|
||||
'serverName' => null,
|
||||
'flags' => DBO_DEFAULT,
|
||||
'variables' => [],
|
||||
'profiler' => null,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,13 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
|
|||
*/
|
||||
public function testFactory() {
|
||||
$m = Database::NEW_UNCONNECTED; // no-connect mode
|
||||
$p = [ 'host' => 'localhost', 'user' => 'me', 'password' => 'myself', 'dbname' => 'i' ];
|
||||
$p = [
|
||||
'host' => 'localhost',
|
||||
'serverName' => 'localdb',
|
||||
'user' => 'me',
|
||||
'password' => 'myself',
|
||||
'dbname' => 'i'
|
||||
];
|
||||
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'mysqli', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySqli', $p, $m ) );
|
||||
|
|
@ -43,6 +49,10 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
|
|||
$this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
|
||||
$x = $p + [ 'dbDirectory' => 'some/file' ];
|
||||
$this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
|
||||
|
||||
$conn = Database::factory( 'sqlite', $p, $m );
|
||||
$this->assertEquals( 'localhost', $conn->getServer() );
|
||||
$this->assertEquals( 'localdb', $conn->getServerName() );
|
||||
}
|
||||
|
||||
public static function provideAddQuotes() {
|
||||
|
|
@ -436,17 +446,23 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
|
|||
'closeConnection',
|
||||
'dataSeek',
|
||||
'doQuery',
|
||||
'fetchObject', 'fetchRow',
|
||||
'fieldInfo', 'fieldName',
|
||||
'getSoftwareLink', 'getServerVersion',
|
||||
'fetchObject',
|
||||
'fetchRow',
|
||||
'fieldInfo',
|
||||
'fieldName',
|
||||
'getSoftwareLink',
|
||||
'getServerVersion',
|
||||
'getType',
|
||||
'indexInfo',
|
||||
'insertId',
|
||||
'lastError', 'lastErrno',
|
||||
'numFields', 'numRows',
|
||||
'lastError',
|
||||
'lastErrno',
|
||||
'numFields',
|
||||
'numRows',
|
||||
'open',
|
||||
'strencode',
|
||||
'tableExists'
|
||||
'tableExists',
|
||||
'getServer'
|
||||
];
|
||||
$db = $this->getMockBuilder( Database::class )
|
||||
->disableOriginalConstructor()
|
||||
|
|
@ -465,7 +481,8 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
|
|||
$wdb->deprecationLogger = static function ( $msg ) {
|
||||
};
|
||||
$wdb->currentDomain = DatabaseDomain::newUnspecified();
|
||||
$wdb->server = 'localhost';
|
||||
|
||||
$db->method( 'getServer' )->willReturn( '*dummy*' );
|
||||
|
||||
return $db;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue