Pass __METHOD__ to DatabaseBase::commit() and DatabaseBase::rollback()
[mediawiki.git] / includes / db / LoadMonitor.php
blob16a0343fb35be5a73134c1de92aed707b7f488bb
1 <?php
2 /**
3 * Database load monitoring
5 * @file
6 * @ingroup Database
7 */
9 /**
10 * An interface for database load monitoring
12 * @ingroup Database
14 interface LoadMonitor {
15 /**
16 * Construct a new LoadMonitor with a given LoadBalancer parent
18 * @param LoadBalancer $parent
20 function __construct( $parent );
22 /**
23 * Perform pre-connection load ratio adjustment.
24 * @param $loads array
25 * @param $group String: the selected query group
26 * @param $wiki String
28 function scaleLoads( &$loads, $group = false, $wiki = false );
30 /**
31 * Perform post-connection backoff.
33 * If the connection is in overload, this should return a backoff factor
34 * which will be used to control polling time. The number of threads
35 * connected is a good measure.
37 * If there is no overload, zero can be returned.
39 * A threshold thread count is given, the concrete class may compare this
40 * to the running thread count. The threshold may be false, which indicates
41 * that the sysadmin has not configured this feature.
43 * @param $conn DatabaseBase
44 * @param $threshold Float
46 function postConnectionBackoff( $conn, $threshold );
48 /**
49 * Return an estimate of replication lag for each server
51 * @param $serverIndexes
52 * @param $wiki
54 * @return array
56 function getLagTimes( $serverIndexes, $wiki );
59 class LoadMonitor_Null implements LoadMonitor {
60 function __construct( $parent ) {
63 function scaleLoads( &$loads, $group = false, $wiki = false ) {
66 function postConnectionBackoff( $conn, $threshold ) {
69 /**
70 * @param $serverIndexes
71 * @param $wiki
72 * @return array
74 function getLagTimes( $serverIndexes, $wiki ) {
75 return array_fill_keys( $serverIndexes, 0 );
79 /**
80 * Basic MySQL load monitor with no external dependencies
81 * Uses memcached to cache the replication lag for a short time
83 * @ingroup Database
85 class LoadMonitor_MySQL implements LoadMonitor {
87 /**
88 * @var LoadBalancer
90 var $parent;
92 /**
93 * @param LoadBalancer $parent
95 function __construct( $parent ) {
96 $this->parent = $parent;
99 /**
100 * @param $loads
101 * @param $group bool
102 * @param $wiki bool
104 function scaleLoads( &$loads, $group = false, $wiki = false ) {
108 * @param $serverIndexes
109 * @param $wiki
110 * @return array
112 function getLagTimes( $serverIndexes, $wiki ) {
113 if ( count( $serverIndexes ) == 1 && reset( $serverIndexes ) == 0 ) {
114 // Single server only, just return zero without caching
115 return array( 0 => 0 );
118 wfProfileIn( __METHOD__ );
119 $expiry = 5;
120 $requestRate = 10;
122 global $wgMemc;
123 if ( empty( $wgMemc ) )
124 $wgMemc = wfGetMainCache();
126 $masterName = $this->parent->getServerName( 0 );
127 $memcKey = wfMemcKey( 'lag_times', $masterName );
128 $times = $wgMemc->get( $memcKey );
129 if ( $times ) {
130 # Randomly recache with probability rising over $expiry
131 $elapsed = time() - $times['timestamp'];
132 $chance = max( 0, ( $expiry - $elapsed ) * $requestRate );
133 if ( mt_rand( 0, $chance ) != 0 ) {
134 unset( $times['timestamp'] );
135 wfProfileOut( __METHOD__ );
136 return $times;
138 wfIncrStats( 'lag_cache_miss_expired' );
139 } else {
140 wfIncrStats( 'lag_cache_miss_absent' );
143 # Cache key missing or expired
145 $times = array();
146 foreach ( $serverIndexes as $i ) {
147 if ($i == 0) { # Master
148 $times[$i] = 0;
149 } elseif ( false !== ( $conn = $this->parent->getAnyOpenConnection( $i ) ) ) {
150 $times[$i] = $conn->getLag();
151 } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) {
152 $times[$i] = $conn->getLag();
156 # Add a timestamp key so we know when it was cached
157 $times['timestamp'] = time();
158 $wgMemc->set( $memcKey, $times, $expiry );
160 # But don't give the timestamp to the caller
161 unset($times['timestamp']);
162 $lagTimes = $times;
164 wfProfileOut( __METHOD__ );
165 return $lagTimes;
169 * @param $conn DatabaseBase
170 * @param $threshold
171 * @return int
173 function postConnectionBackoff( $conn, $threshold ) {
174 if ( !$threshold ) {
175 return 0;
177 $status = $conn->getMysqlStatus("Thread%");
178 if ( $status['Threads_running'] > $threshold ) {
179 $server = $conn->getProperty( 'mServer' );
180 wfLogDBError( "LB backoff from $server - Threads_running = {$status['Threads_running']}\n" );
181 return $status['Threads_connected'];
182 } else {
183 return 0;