* Skip COMMIT query when no write queries have been done.

* Improvement to ChronologyProtector: only record the master position if a write query was done. This should help to avoid the worst of the ChronologyProtector side-effects, such as having action=raw CSS requests block for a time equivalent to the slave lag on every page view, while maintaining the benefits, like preventing a 404 from being displayed after page creation.
This commit is contained in:
Tim Starling 2009-02-17 14:06:42 +00:00
parent fda50654b3
commit 8653947b06
3 changed files with 41 additions and 10 deletions

View file

@ -26,6 +26,7 @@ class Database {
#------------------------------------------------------------------------------
protected $mLastQuery = '';
protected $mDoneWrites = false;
protected $mPHPError = false;
protected $mServer, $mUser, $mPassword, $mConn = null, $mDBname;
@ -210,7 +211,14 @@ class Database {
* @return String
*/
function lastQuery() { return $this->mLastQuery; }
/**
* Returns true if the connection may have been used for write queries.
* Should return true if unsure.
*/
function doneWrites() { return $this->mDoneWrites; }
/**
* Is a connection to the database open?
* @return Boolean
@ -492,6 +500,14 @@ class Database {
}
}
/**
* Determine whether a query writes to the DB.
* Should return true if unsure.
*/
function isWriteQuery( $sql ) {
return !preg_match( '/^(?:SELECT|BEGIN|COMMIT|SET|SHOW)\b/i', $sql );
}
/**
* Usually aborts on failure. If errors are explicitly ignored, returns success.
*
@ -527,6 +543,11 @@ class Database {
}
$this->mLastQuery = $sql;
if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) {
// Set a flag indicating that writes have been done
wfDebug( __METHOD__.": Writes done: $sql\n" );
$this->mDoneWrites = true;
}
# Add a comment for easy SHOW PROCESSLIST interpretation
#if ( $fname ) {

View file

@ -236,15 +236,25 @@ class ChronologyProtector {
* @param LoadBalancer $lb
*/
function shutdownLB( $lb ) {
if ( session_id() != '' && $lb->getServerCount() > 1 ) {
$masterName = $lb->getServerName( 0 );
if ( !isset( $this->shutdownPos[$masterName] ) ) {
$pos = $lb->getMasterPos();
$info = $lb->parentInfo();
wfDebug( __METHOD__.": LB " . $info['id'] . " has master pos $pos\n" );
$this->shutdownPos[$masterName] = $pos;
}
// Don't start a session, don't bother with non-replicated setups
if ( strval( session_id() ) == '' || $lb->getServerCount() <= 1 ) {
return;
}
$masterName = $lb->getServerName( 0 );
if ( isset( $this->shutdownPos[$masterName] ) ) {
// Already done
return;
}
// Only save the position if writes have been done on the connection
$db = $lb->getAnyOpenConnection( 0 );
$info = $lb->parentInfo();
if ( !$db || !$db->doneWrites() ) {
wfDebug( __METHOD__.": LB {$info['id']}, no writes done\n" );
return;
}
$pos = $db->getMasterPos();
wfDebug( __METHOD__.": LB {$info['id']} has master pos $pos\n" );
$this->shutdownPos[$masterName] = $pos;
}
/**

View file

@ -824,7 +824,7 @@ class LoadBalancer {
continue;
}
foreach ( $conns2[$masterIndex] as $conn ) {
if ( $conn->lastQuery() != '' ) {
if ( $conn->doneWrites() ) {
$conn->commit();
}
}