Cleanups to SqlBagOStuff
authorAaron Schulz <aschulz@wikimedia.org>
Wed, 24 Aug 2016 21:02:15 +0000 (14:02 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Thu, 25 Aug 2016 02:38:14 +0000 (19:38 -0700)
* Keep track of the custom LoadBalancer when it makes one.
* Use the custom LoadBalancer to wait for slaves if one
  was used, rather than the main singleton.
* Only wait on the slaves in the LoadBalancer if the
  main DBs are being used.

Change-Id: I11de814306c44f27e0c33b08b5921c0fd4cdc24f

includes/objectcache/SqlBagOStuff.php

index 9ab28aa..7a89991 100644 (file)
@@ -48,6 +48,8 @@ class SqlBagOStuff extends BagOStuff {
        /** @var int */
        protected $syncTimeout = 3;
 
+       /** @var LoadBalancer|null */
+       protected $separateMainLB;
        /** @var array */
        protected $conns;
        /** @var array UNIX timestamps */
@@ -114,6 +116,7 @@ class SqlBagOStuff extends BagOStuff {
                        $this->serverInfos = [ $params['server'] ];
                        $this->numServers = count( $this->serverInfos );
                } else {
+                       // Default to using the main wiki's database servers
                        $this->serverInfos = false;
                        $this->numServers = 1;
                }
@@ -132,6 +135,23 @@ class SqlBagOStuff extends BagOStuff {
                $this->slaveOnly = !empty( $params['slaveOnly'] );
        }
 
+       protected function getSeparateMainLB() {
+               global $wgDBtype;
+
+               if ( $wgDBtype === 'mysql' && $this->usesMainDB() ) {
+                       if ( !$this->separateMainLB ) {
+                               // We must keep a separate connection to MySQL in order to avoid deadlocks
+                               $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+                               $this->separateMainLB = $lbFactory->newMainLB();
+                       }
+                       return $this->separateMainLB;
+               } else {
+                       // However, SQLite has an opposite behavior. And PostgreSQL needs to know
+                       // if we are in transaction or not (@TODO: find some PostgreSQL work-around).
+                       return null;
+               }
+       }
+
        /**
         * Get a connection to the specified database
         *
@@ -163,16 +183,13 @@ class SqlBagOStuff extends BagOStuff {
                                $db = DatabaseBase::factory( $type, $info );
                                $db->clearFlag( DBO_TRX );
                        } else {
-                               // We must keep a separate connection to MySQL in order to avoid deadlocks
-                               // However, SQLite has an opposite behavior. And PostgreSQL needs to know
-                               // if we are in transaction or not (@TODO: find some work-around).
                                $index = $this->slaveOnly ? DB_SLAVE : DB_MASTER;
-                               if ( wfGetDB( $index )->getType() == 'mysql' ) {
-                                       $lb = wfGetLBFactory()->newMainLB();
-                                       $db = $lb->getConnection( $index );
+                               if ( $this->getSeparateMainLB() ) {
+                                       $db = $this->getSeparateMainLB()->getConnection( $index );
                                        $db->clearFlag( DBO_TRX ); // auto-commit mode
                                } else {
                                        $db = wfGetDB( $index );
+                                       // Can't mess with transaction rounds (DBO_TRX) :(
                                }
                        }
                        $this->logger->debug( sprintf( "Connection %s will be used for SqlBagOStuff", $db ) );
@@ -782,17 +799,20 @@ class SqlBagOStuff extends BagOStuff {
 
        protected function waitForSlaves() {
                if ( $this->usesMainDB() ) {
+                       $lb = $this->getSeparateMainLB()
+                               ?: MediaWikiServices::getInstance()->getDBLoadBalancer();
                        // Main LB is used; wait for any slaves to catch up
                        try {
-                               $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
-                               $lbFactory->waitForReplication( [ 'wiki' => wfWikiID() ] );
-                               return true;
+                               $pos = $lb->getMasterPos();
+                               if ( $pos ) {
+                                       return $lb->waitForAll( $pos, 3 );
+                               }
                        } catch ( DBReplicationWaitError $e ) {
                                return false;
                        }
-               } else {
-                       // Custom DB server list; probably doesn't use replication
-                       return true;
                }
+
+               // Custom DB server list; probably doesn't use replication
+               return true;
        }
 }