From 958a13b0259cada9a78566d0792b40e15075892e Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Tue, 23 Sep 2014 15:38:44 -0700 Subject: [PATCH] Created DatabaseBase::trxTimestamp method and added usage in ActiveUsers query Change-Id: Iba3c83ce8010583908f9dbaa8348f7226f524793 --- includes/db/Database.php | 25 ++++++++++++++++++++++++ includes/specials/SpecialActiveusers.php | 18 +++++++++-------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/includes/db/Database.php b/includes/db/Database.php index 9b783a99d6..29642d0914 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -272,9 +272,20 @@ abstract class DatabaseBase implements IDatabase, DatabaseType { * Either a short hexidecimal string if a transaction is active or "" * * @var string + * @see DatabaseBase::mTrxLevel */ protected $mTrxShortId = ''; + /** + * The UNIX time that the transaction started. Callers can assume that if + * snapshot isolation is used, then the data is *at least* up to date to that + * point (possibly more up-to-date since the first SELECT defines the snapshot). + * + * @var float|null + * @see DatabaseBase::mTrxLevel + */ + private $mTrxTimestamp = null; + /** * Remembers the function name given for starting the most recent transaction via begin(). * Used to provide additional context for error reporting. @@ -419,6 +430,19 @@ abstract class DatabaseBase implements IDatabase, DatabaseType { return $this->mTrxLevel; } + /** + * Get the UNIX timestamp of the time that the transaction was established + * + * This can be used to reason about the staleness of SELECT data + * in REPEATABLE-READ transaction isolation level. + * + * @return float|null Returns null if there is not active transaction + * @since 1.25 + */ + public function trxTimestamp() { + return $this->mTrxLevel ? $this->mTrxTimestamp : null; + } + /** * Get/set the number of errors logged. Only useful when errors are ignored * @param int $count The count to set, or omitted to leave it unchanged. @@ -3512,6 +3536,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType { } $this->doBegin( $fname ); + $this->mTrxTimestamp = microtime( true ); $this->mTrxFname = $fname; $this->mTrxDoneWrites = false; $this->mTrxAutomatic = false; diff --git a/includes/specials/SpecialActiveusers.php b/includes/specials/SpecialActiveusers.php index 07e1be1933..10ab46a237 100644 --- a/includes/specials/SpecialActiveusers.php +++ b/includes/specials/SpecialActiveusers.php @@ -339,21 +339,19 @@ class SpecialActiveUsers extends SpecialPage { return false; // exclusive update (avoids duplicate entries) } - $now = time(); + $nowUnix = time(); + // Get the last-updated timestamp for the cache $cTime = $dbw->selectField( 'querycache_info', 'qci_timestamp', array( 'qci_type' => 'activeusers' ) ); $cTimeUnix = $cTime ? wfTimestamp( TS_UNIX, $cTime ) : 1; - // If a transaction was already started, it might have an old - // snapshot, so kludge the timestamp range a few seconds back. - $cTimeUnix -= 5; // Pick the date range to fetch from. This is normally from the last // update to till the present time, but has a limited window for sanity. // If the window is limited, multiple runs are need to fully populate it. - $sTimestamp = max( $cTimeUnix, $now - $days * 86400 ); - $eTimestamp = min( $sTimestamp + $window, $now ); + $sTimestamp = max( $cTimeUnix, $nowUnix - $days * 86400 ); + $eTimestamp = min( $sTimestamp + $window, $nowUnix ); // Get all the users active since the last update $res = $dbw->select( @@ -381,7 +379,7 @@ class SpecialActiveUsers extends SpecialPage { $dbw->delete( 'querycachetwo', array( 'qcc_type' => 'activeusers', - 'qcc_value < ' . $dbw->addQuotes( $now - $days * 86400 ) // TS_UNIX + 'qcc_value < ' . $dbw->addQuotes( $nowUnix - $days * 86400 ) // TS_UNIX ), __METHOD__ ); @@ -425,11 +423,15 @@ class SpecialActiveUsers extends SpecialPage { } } + // If a transaction was already started, it might have an old + // snapshot, so kludge the timestamp range back as needed. + $asOfTimestamp = min( $eTimestamp, (int)$dbw->trxTimestamp() ); + // Touch the data freshness timestamp $dbw->replace( 'querycache_info', array( 'qci_type' ), array( 'qci_type' => 'activeusers', - 'qci_timestamp' => $dbw->timestamp( $eTimestamp ) ), // not always $now + 'qci_timestamp' => $dbw->timestamp( $asOfTimestamp ) ), // not always $now __METHOD__ ); -- 2.20.1