From: Aaron Schulz Date: Fri, 25 Sep 2015 19:53:04 +0000 (-0700) Subject: Added pt-heartbeat support to DatabaseMysqlBase X-Git-Tag: 1.31.0-rc.0~9589 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/password.php?a=commitdiff_plain;h=ff34e3d464be285b08b157ab707f1704657f71a5;p=lhc%2Fweb%2Fwiklou.git Added pt-heartbeat support to DatabaseMysqlBase Bug: T111266 Bug: T19179 Change-Id: I04c93d5c7389fbb8fba633d955591b30a9504f31 --- diff --git a/includes/db/DatabaseMysqlBase.php b/includes/db/DatabaseMysqlBase.php index 61a05652d1..ac7ce1086b 100644 --- a/includes/db/DatabaseMysqlBase.php +++ b/includes/db/DatabaseMysqlBase.php @@ -32,10 +32,33 @@ abstract class DatabaseMysqlBase extends DatabaseBase { /** @var MysqlMasterPos */ protected $lastKnownSlavePos; + /** @var string Method to detect slave lag */ + protected $lagDetectionMethod; + + /** @var BagOStuff APC cache */ + protected $srvCache; /** @var string|null */ private $serverVersion = null; + /** + * Additional $params include: + * - lagDetectionMethod : set to one of (Seconds_Behind_Master,pt-heartbeat). + * pt-heartbeat assumes the table is at heartbeat.heartbeat + * and uses UTC timestamps in the heartbeat.ts column. + * (https://www.percona.com/doc/percona-toolkit/2.2/pt-heartbeat.html) + * @param array $params + */ + function __construct( array $params ) { + parent::__construct( $params ); + + $this->lagDetectionMethod = isset( $params['lagDetectionMethod'] ) + ? $params['lagDetectionMethod'] + : 'Seconds_Behind_Master'; + + $this->srvCache = ObjectCache::newAccelerator( 'hash' ); + } + /** * @return string */ @@ -604,26 +627,55 @@ abstract class DatabaseMysqlBase extends DatabaseBase { * @return int */ function getLag() { - return $this->getLagFromSlaveStatus(); + if ( $this->lagDetectionMethod === 'pt-heartbeat' ) { + return $this->getLagFromPtHeartbeat(); + } else { + return $this->getLagFromSlaveStatus(); + } } /** * @return bool|int */ - function getLagFromSlaveStatus() { + protected function getLagFromSlaveStatus() { $res = $this->query( 'SHOW SLAVE STATUS', __METHOD__ ); - if ( !$res ) { - return false; + $row = $res ? $res->fetchObject() : false; + if ( $row && strval( $row->Seconds_Behind_Master ) !== '' ) { + return intval( $row->Seconds_Behind_Master ); } - $row = $res->fetchObject(); - if ( !$row ) { - return false; + + return false; + } + + /** + * @return bool|float + */ + protected function getLagFromPtHeartbeat() { + $key = wfMemcKey( 'mysql', 'master-server-id', $this->getServer() ); + $masterId = intval( $this->srvCache->get( $key ) ); + if ( !$masterId ) { + $res = $this->query( 'SHOW SLAVE STATUS', __METHOD__ ); + $row = $res ? $res->fetchObject() : false; + if ( $row && strval( $row->Master_Server_Id ) !== '' ) { + $masterId = intval( $row->Master_Server_Id ); + $this->srvCache->set( $key, $masterId, 30 ); + } } - if ( strval( $row->Seconds_Behind_Master ) === '' ) { + + if ( !$masterId ) { return false; - } else { - return intval( $row->Seconds_Behind_Master ); } + + $res = $this->query( + "SELECT TIMESTAMPDIFF(MICROSECOND,ts,UTC_TIMESTAMP(6)) AS Lag " . + "FROM heartbeat.heartbeat WHERE server_id = $masterId" + ); + $row = $res ? $res->fetchObject() : false; + if ( $row ) { + return max( floatval( $row->Lag ) / 1e6, 0.0 ); + } + + return false; } /**