* 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.
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.
}
$this->doBegin( $fname );
+ $this->mTrxTimestamp = microtime( true );
$this->mTrxFname = $fname;
$this->mTrxDoneWrites = false;
$this->mTrxAutomatic = false;
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(
$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__
);
}
}
+ // 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__
);