[SiteStatsUpdate] Reduced contention by using a new lockIsFree() DB function.
authorAaron <aschulz@wikimedia.org>
Thu, 10 May 2012 22:42:59 +0000 (15:42 -0700)
committerAaron <aschulz@wikimedia.org>
Thu, 10 May 2012 22:48:58 +0000 (15:48 -0700)
* Note: follows up a4b3979160c3ae895d4763967c485380448ce8c0
* Cleanup up transaction statements a bit; transactions don't effect the lock calls
* Also made DatabaseMysql::unlock() actually return a bool

Change-Id: Iade2efa94165b6918eae0863716cc163f36a07b8

includes/SiteStats.php
includes/db/Database.php
includes/db/DatabaseMysql.php

index fec24e9..10aed9c 100644 (file)
@@ -286,14 +286,13 @@ class SiteStatsUpdate implements DeferrableUpdate {
                        $this->doUpdatePendingDeltas();
                } else {
                        $dbw = wfGetDB( DB_MASTER );
-                       // Need a separate transaction because this a global lock
-                       $dbw->begin( __METHOD__ );
 
                        $lockKey = wfMemcKey( 'site_stats' ); // prepend wiki ID
                        if ( $rate ) {
                                // Lock the table so we don't have double DB/memcached updates
-                               if ( !$dbw->lock( $lockKey, __METHOD__, 1 ) ) {
-                                       $dbw->commit( __METHOD__ );
+                               if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
+                                       || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout
+                               ) {
                                        $this->doUpdatePendingDeltas();
                                        return;
                                }
@@ -307,6 +306,9 @@ class SiteStatsUpdate implements DeferrableUpdate {
                                $this->images   += ( $pd['ss_images']['+'] - $pd['ss_images']['-'] );
                        }
 
+                       // Need a separate transaction because this a global lock
+                       $dbw->begin( __METHOD__ );
+
                        // Build up an SQL query of deltas and apply them...
                        $updates = '';
                        $this->appendUpdate( $updates, 'ss_total_views', $this->views );
index 6eb51af..b972f3b 100644 (file)
@@ -3364,6 +3364,18 @@ abstract class DatabaseBase implements DatabaseType {
                return 'CONCAT(' . implode( ',', $stringList ) . ')';
        }
 
+       /**
+        * Check to see if a named lock is available. This is non-blocking.
+        *
+        * @param $lockName String: name of lock to poll
+        * @param $method String: name of method calling us
+        * @return Boolean
+        * @since 1.20
+        */
+       public function lockIsFree( $lockName, $method ) {
+               return true;
+       }
+
        /**
         * Acquire a named lock
         *
index c334c38..8550635 100644 (file)
@@ -686,6 +686,21 @@ class DatabaseMysql extends DatabaseBase {
                return parent::streamStatementEnd( $sql, $newLine );
        }
 
+       /**
+        * Check to see if a named lock is available. This is non-blocking.
+        *
+        * @param $lockName String: name of lock to poll
+        * @param $method String: name of method calling us
+        * @return Boolean
+        * @since 1.20
+        */
+       public function lockIsFree( $lockName, $method ) {
+               $lockName = $this->addQuotes( $lockName );
+               $result = $this->query( "SELECT IS_FREE_LOCK($lockName) AS lockstatus", $method );
+               $row = $this->fetchObject( $result );
+               return ( $row->lockstatus == 1 );
+       }
+
        /**
         * @param $lockName string
         * @param $method string
@@ -715,7 +730,7 @@ class DatabaseMysql extends DatabaseBase {
                $lockName = $this->addQuotes( $lockName );
                $result = $this->query( "SELECT RELEASE_LOCK($lockName) as lockstatus", $method );
                $row = $this->fetchObject( $result );
-               return $row->lockstatus;
+               return ( $row->lockstatus == 1 );
        }
 
        /**