* in maintenance scripts, to avoid causing too much lag. Of course, this is
* a no-op if there are no slaves.
*
- * @param int|bool $maxLag (deprecated)
+ * @param float|null $ifWritesSince Only wait if writes were done since this UNIX timestamp
* @param string|bool $wiki Wiki identifier accepted by wfGetLB
* @param string|bool $cluster Cluster name accepted by LBFactory. Default: false.
*/
-function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
+function wfWaitForSlaves( $ifWritesSince = false, $wiki = false, $cluster = false ) {
+ // B/C: first argument used to be "max seconds of lag"; ignore such values
+ $ifWritesSince = ( $ifWritesSince > 1e9 ) ? $ifWritesSince : false;
+
if ( $cluster !== false ) {
$lb = wfGetLBFactory()->getExternalLB( $cluster );
} else {
// bug 27975 - Don't try to wait for slaves if there are none
// Prevents permission error when getting master position
if ( $lb->getServerCount() > 1 ) {
+ if ( $ifWritesSince && !$lb->isOpen( DB_MASTER ) ) {
+ return; // assume no writes done
+ }
$dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
+ if ( $ifWritesSince && $dbw->lastDoneWrites() < $ifWritesSince ) {
+ return; // no writes since the last wait
+ }
$pos = $dbw->getMasterPos();
// The DBMS may not support getMasterPos() or the whole
// load balancer might be fake (e.g. $wgAllDBsAreLocalhost).
* @return bool
*/
public function doneWrites() {
- return $this->mDoneWrites;
+ return (bool)$this->mDoneWrites;
+ }
+
+ /**
+ * Returns the last time the connection may have been used for write queries.
+ * Should return a timestamp if unsure.
+ *
+ * @return int|float UNIX timestamp or false
+ * @since 1.24
+ */
+ public function lastDoneWrites() {
+ return $this->mDoneWrites ?: false;
}
/**
global $wgUser, $wgDebugDBTransactions;
$this->mLastQuery = $sql;
- if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) {
+ if ( $this->isWriteQuery( $sql ) ) {
# Set a flag indicating that writes have been done
wfDebug( __METHOD__ . ': Writes done: ' . DatabaseBase::generalizeSQL( $sql ) . "\n" );
- $this->mDoneWrites = true;
+ $this->mDoneWrites = microtime( true );
}
# Add a comment for easy SHOW PROCESSLIST interpretation
$jobsRun = 0; // counter
$flags = JobQueueGroup::USE_CACHE;
- $lastTime = time(); // time since last slave check
+ $lastTime = microtime( true ); // time since last slave check
do {
$backoffs = array_filter( $backoffs, $backoffExpireFunc );
$blacklist = $noThrottle ? array() : array_keys( $backoffs );
}
// Don't let any of the main DB slaves get backed up
- $timePassed = time() - $lastTime;
+ $timePassed = microtime( true ) - $lastTime;
if ( $timePassed >= 5 || $timePassed < 0 ) {
- wfWaitForSlaves();
- $lastTime = time();
+ wfWaitForSlaves( $lastTime );
+ $lastTime = microtime( true );
}
// Don't let any queue slaves/backups fall behind
if ( $jobsRun > 0 && ( $jobsRun % 100 ) == 0 ) {