Commit all connections after each job
authorNik Everett <neverett@wikimedia.org>
Fri, 29 May 2015 22:07:27 +0000 (18:07 -0400)
committerNik Everett <neverett@wikimedia.org>
Mon, 1 Jun 2015 21:43:43 +0000 (17:43 -0400)
If you don't commit the slave connections then they keep their old snapshots.
This clears the snapshots so they don't get out of date views of the world.

Bug: T100838
Change-Id: I1f6f910d88324beb589b2ad9466d8786376eda55

includes/db/LBFactory.php
includes/jobqueue/JobRunner.php

index 4551e2d..0742df2 100644 (file)
@@ -177,6 +177,15 @@ abstract class LBFactory {
                }, array( $methodName, $args ) );
        }
 
+       /**
+        * Commit on all connections. Done for two reasons:
+        * 1. To commit changes to the masters.
+        * 2. To release the snapshot on all connections, master and slave.
+        */
+       public function commitAll() {
+               $this->forEachLBCallMethod( 'commitAll' );
+       }
+
        /**
         * Commit changes on all master connections
         */
index b04ab28..bb12298 100644 (file)
@@ -128,7 +128,7 @@ class JobRunner implements LoggerAwareInterface {
                $group = JobQueueGroup::singleton();
                
                // Flush any pending DB writes for sanity
-               wfGetLBFactory()->commitMasterChanges();
+               wfGetLBFactory()->commitAll();
 
                // Some jobs types should not run until a certain timestamp
                $backoffs = array(); // map of (type => UNIX expiry)
@@ -190,6 +190,14 @@ class JobRunner implements LoggerAwareInterface {
                                        $error = get_class( $e ) . ': ' . $e->getMessage();
                                        MWExceptionHandler::logException( $e );
                                }
+                               // Commit all outstanding connections that are in a transaction
+                               // to get a fresh repeatable read snapshot on every connection.
+                               // This is important because if you have an old snapshot on the
+                               // database you could run the job incorrectly. Its possible, for
+                               // example, to pick up a RefreshLinksJob for a new page that isn't
+                               // even visible to the snapshot. The snapshot could have been
+                               // created before the page. Fresh snapshots will see the page.
+                               wfGetLBFactory()->commitAll();
                                $timeMs = intval( ( microtime( true ) - $jobStartTime ) * 1000 );
                                $timeMsTotal += $timeMs;
                                $profiler->scopedProfileOut( $psection );
@@ -410,7 +418,10 @@ class JobRunner implements LoggerAwareInterface {
        }
 
        /**
-        * Commit any DB master changes from a job on all load balancers
+        * Issue a commit on all masters who are currently in a transaction and have
+        * made changes to the database. It also supports sometimes waiting for the
+        * local wiki's slaves to catch up. See the documentation for
+        * $wgJobSerialCommitThreshold for more.
         *
         * @param Job $job
         * @throws DBError