* Skip COMMIT query when no write queries have been done.
authorTim Starling <tstarling@users.mediawiki.org>
Tue, 17 Feb 2009 14:06:42 +0000 (14:06 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Tue, 17 Feb 2009 14:06:42 +0000 (14:06 +0000)
* 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.

includes/db/Database.php
includes/db/LBFactory.php
includes/db/LoadBalancer.php

index 3839918..97b7746 100644 (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 ) {
index 256875d..3876d71 100644 (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;
        }
 
        /**
index f847fe2..0b8ef05 100644 (file)
@@ -824,7 +824,7 @@ class LoadBalancer {
                                continue;
                        }
                        foreach ( $conns2[$masterIndex] as $conn ) {
-                               if ( $conn->lastQuery() != '' ) {
+                               if ( $conn->doneWrites() ) {
                                        $conn->commit();
                                }
                        }