rdbms: avoid lag estimates in getLagFromPtHeartbeat ruined by snapshots
authorAaron Schulz <aschulz@wikimedia.org>
Thu, 29 Mar 2018 23:30:38 +0000 (16:30 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Sat, 31 Mar 2018 01:39:57 +0000 (01:39 +0000)
Bug: T190960
Change-Id: I57dd8d3d0ca96d6fb2f9e83f062f29b1d53224dd

includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseMysqlBase.php
includes/libs/rdbms/loadmonitor/LoadMonitor.php

index 00d9b0b..d736477 100644 (file)
@@ -3682,7 +3682,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @return array|null ('lag': seconds or false on error, 'since': UNIX timestamp of BEGIN)
         * @since 1.27
         */
         * @return array|null ('lag': seconds or false on error, 'since': UNIX timestamp of BEGIN)
         * @since 1.27
         */
-       protected function getTransactionLagStatus() {
+       final protected function getTransactionLagStatus() {
                return $this->trxLevel
                        ? [ 'lag' => $this->trxReplicaLag, 'since' => $this->trxTimestamp() ]
                        : null;
                return $this->trxLevel
                        ? [ 'lag' => $this->trxReplicaLag, 'since' => $this->trxTimestamp() ]
                        : null;
index 315c9eb..bc4beba 100644 (file)
@@ -763,6 +763,17 @@ abstract class DatabaseMysqlBase extends Database {
        protected function getLagFromPtHeartbeat() {
                $options = $this->lagDetectionOptions;
 
        protected function getLagFromPtHeartbeat() {
                $options = $this->lagDetectionOptions;
 
+               if ( $this->trxLevel ) {
+                       // Avoid returning higher and higher lag value due to snapshot age
+                       // given that the isolation level will typically be REPEATABLE-READ
+                       $this->queryLogger->warning(
+                               "Using cached lag value for {db_server} due to active transaction",
+                               $this->getLogContext( [ 'method' => __METHOD__ ] )
+                       );
+
+                       return $this->getTransactionLagStatus()['lag'];
+               }
+
                if ( isset( $options['conds'] ) ) {
                        // Best method for multi-DC setups: use logical channel names
                        $data = $this->getHeartbeatData( $options['conds'] );
                if ( isset( $options['conds'] ) ) {
                        // Best method for multi-DC setups: use logical channel names
                        $data = $this->getHeartbeatData( $options['conds'] );
index 50c878d..3372839 100644 (file)
@@ -157,7 +157,9 @@ class LoadMonitor implements ILoadMonitor {
                        }
 
                        $conn = $this->parent->getAnyOpenConnection( $i );
                        }
 
                        $conn = $this->parent->getAnyOpenConnection( $i );
-                       if ( $conn ) {
+                       if ( $conn && !$conn->trxLevel() ) {
+                               # Handles with open transactions are avoided since they might be subject
+                               # to REPEATABLE-READ snapshots, which could affect the lag estimate query.
                                $close = false; // already open
                        } else {
                                $conn = $this->parent->openConnection( $i, '' );
                                $close = false; // already open
                        } else {
                                $conn = $this->parent->openConnection( $i, '' );