mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 06:15:19 +08:00
Fix #17991: Improve yii\db\Connection
master and slave failover, no connection attempt was made when all servers are marked as unavailable
This commit is contained in:
@ -13,6 +13,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #17960: Fix unsigned primary key type mapping for SQLite (bizley)
|
||||
- Enh #17758: `Query::withQuery()` can be used for CTE (sartor)
|
||||
- Bug #17974: Fix ActiveRelationTrait compatibility with PHP 7.4 (Ximich)
|
||||
- Bug #17991: Improve `yii\db\Connection` master and slave failover, no connection attempt was made when all servers are marked as unavailable (cebe)
|
||||
- Enh #17993: Added `yii\i18n\Formatter::$currencyDecimalSeparator` to allow setting custom symbols for currency decimal in IntlNumberFormatter (XPOHOC269)
|
||||
- Bug #18000: PK value of Oracle ActiveRecord is missing after save (mankwok)
|
||||
- Enh #18006: Allow SameSite cookie pre PHP 7.3 (scottix)
|
||||
|
@ -332,6 +332,8 @@ class Connection extends Component
|
||||
* the health status of the DB servers specified in [[masters]] and [[slaves]].
|
||||
* This is used only when read/write splitting is enabled or [[masters]] is not empty.
|
||||
* Set boolean `false` to disabled server status caching.
|
||||
* @see openFromPoolSequentially() for details about the failover behavior.
|
||||
* @see serverRetryInterval
|
||||
*/
|
||||
public $serverStatusCache = 'cache';
|
||||
/**
|
||||
@ -1099,12 +1101,16 @@ class Connection extends Component
|
||||
|
||||
/**
|
||||
* Opens the connection to a server in the pool.
|
||||
* This method implements the load balancing among the given list of the servers.
|
||||
*
|
||||
* This method implements load balancing and failover among the given list of the servers.
|
||||
* Connections will be tried in random order.
|
||||
* For details about the failover behavior, see [[openFromPoolSequentially]].
|
||||
*
|
||||
* @param array $pool the list of connection configurations in the server pool
|
||||
* @param array $sharedConfig the configuration common to those given in `$pool`.
|
||||
* @return Connection the opened DB connection, or `null` if no server is available
|
||||
* @throws InvalidConfigException if a configuration does not specify "dsn"
|
||||
* @see openFromPoolSequentially
|
||||
*/
|
||||
protected function openFromPool(array $pool, array $sharedConfig)
|
||||
{
|
||||
@ -1114,13 +1120,26 @@ class Connection extends Component
|
||||
|
||||
/**
|
||||
* Opens the connection to a server in the pool.
|
||||
* This method implements the load balancing among the given list of the servers.
|
||||
* Connections will be tried in sequential order.
|
||||
*
|
||||
* This method implements failover among the given list of servers.
|
||||
* Connections will be tried in sequential order. The first successful connection will return.
|
||||
*
|
||||
* If [[serverStatusCache]] is configured, this method will cache information about
|
||||
* unreachable servers and does not try to connect to these for the time configured in [[serverRetryInterval]].
|
||||
* This helps to keep the application stable when some servers are unavailable. Avoiding
|
||||
* connection attempts to unavailable servers saves time when the connection attempts fail due to timeout.
|
||||
*
|
||||
* If none of the servers are available the status cache is ignored and connection attempts are made to all
|
||||
* servers (Since version 2.0.35). This is to avoid downtime when all servers are unavailable for a short time.
|
||||
* After a successful connection attempt the server is marked as avaiable again.
|
||||
*
|
||||
* @param array $pool the list of connection configurations in the server pool
|
||||
* @param array $sharedConfig the configuration common to those given in `$pool`.
|
||||
* @return Connection the opened DB connection, or `null` if no server is available
|
||||
* @throws InvalidConfigException if a configuration does not specify "dsn"
|
||||
* @since 2.0.11
|
||||
* @see openFromPool
|
||||
* @see serverStatusCache
|
||||
*/
|
||||
protected function openFromPoolSequentially(array $pool, array $sharedConfig)
|
||||
{
|
||||
@ -1134,8 +1153,8 @@ class Connection extends Component
|
||||
|
||||
$cache = is_string($this->serverStatusCache) ? Yii::$app->get($this->serverStatusCache, false) : $this->serverStatusCache;
|
||||
|
||||
foreach ($pool as $config) {
|
||||
$config = array_merge($sharedConfig, $config);
|
||||
foreach ($pool as $i => $config) {
|
||||
$pool[$i] = $config = array_merge($sharedConfig, $config);
|
||||
if (empty($config['dsn'])) {
|
||||
throw new InvalidConfigException('The "dsn" option must be specified.');
|
||||
}
|
||||
@ -1158,6 +1177,30 @@ class Connection extends Component
|
||||
// mark this server as dead and only retry it after the specified interval
|
||||
$cache->set($key, 1, $this->serverRetryInterval);
|
||||
}
|
||||
// exclude server from retry below
|
||||
unset($pool[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cache instanceof CacheInterface) {
|
||||
// if server status cache is enabled and no server is available
|
||||
// ignore the cache and try to connect anyway
|
||||
// $pool now only contains servers we did not already try in the loop above
|
||||
foreach ($pool as $config) {
|
||||
|
||||
/* @var $db Connection */
|
||||
$db = Yii::createObject($config);
|
||||
try {
|
||||
$db->open();
|
||||
} catch (\Exception $e) {
|
||||
Yii::warning("Connection ({$config['dsn']}) failed: " . $e->getMessage(), __METHOD__);
|
||||
continue;
|
||||
}
|
||||
|
||||
// mark this server as available again after successful connection
|
||||
$cache->delete([__METHOD__, $config['dsn']]);
|
||||
|
||||
return $db;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user