* 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:
parent
fda50654b3
commit
8653947b06
3 changed files with 41 additions and 10 deletions
|
|
@ -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 ) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -824,7 +824,7 @@ class LoadBalancer {
|
|||
continue;
|
||||
}
|
||||
foreach ( $conns2[$masterIndex] as $conn ) {
|
||||
if ( $conn->lastQuery() != '' ) {
|
||||
if ( $conn->doneWrites() ) {
|
||||
$conn->commit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue