Index: trunk/phase3/includes/db/Database.php |
— | — | @@ -26,6 +26,7 @@ |
27 | 27 | #------------------------------------------------------------------------------ |
28 | 28 | |
29 | 29 | protected $mLastQuery = ''; |
| 30 | + protected $mDoneWrites = false; |
30 | 31 | protected $mPHPError = false; |
31 | 32 | |
32 | 33 | protected $mServer, $mUser, $mPassword, $mConn = null, $mDBname; |
— | — | @@ -210,8 +211,15 @@ |
211 | 212 | * @return String |
212 | 213 | */ |
213 | 214 | function lastQuery() { return $this->mLastQuery; } |
214 | | - |
| 215 | + |
| 216 | + |
215 | 217 | /** |
| 218 | + * Returns true if the connection may have been used for write queries. |
| 219 | + * Should return true if unsure. |
| 220 | + */ |
| 221 | + function doneWrites() { return $this->mDoneWrites; } |
| 222 | + |
| 223 | + /** |
216 | 224 | * Is a connection to the database open? |
217 | 225 | * @return Boolean |
218 | 226 | */ |
— | — | @@ -493,6 +501,14 @@ |
494 | 502 | } |
495 | 503 | |
496 | 504 | /** |
| 505 | + * Determine whether a query writes to the DB. |
| 506 | + * Should return true if unsure. |
| 507 | + */ |
| 508 | + function isWriteQuery( $sql ) { |
| 509 | + return !preg_match( '/^(?:SELECT|BEGIN|COMMIT|SET|SHOW)\b/i', $sql ); |
| 510 | + } |
| 511 | + |
| 512 | + /** |
497 | 513 | * Usually aborts on failure. If errors are explicitly ignored, returns success. |
498 | 514 | * |
499 | 515 | * @param $sql String: SQL query |
— | — | @@ -527,6 +543,11 @@ |
528 | 544 | } |
529 | 545 | |
530 | 546 | $this->mLastQuery = $sql; |
| 547 | + if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) { |
| 548 | + // Set a flag indicating that writes have been done |
| 549 | + wfDebug( __METHOD__.": Writes done: $sql\n" ); |
| 550 | + $this->mDoneWrites = true; |
| 551 | + } |
531 | 552 | |
532 | 553 | # Add a comment for easy SHOW PROCESSLIST interpretation |
533 | 554 | #if ( $fname ) { |
Index: trunk/phase3/includes/db/LBFactory.php |
— | — | @@ -236,15 +236,25 @@ |
237 | 237 | * @param LoadBalancer $lb |
238 | 238 | */ |
239 | 239 | function shutdownLB( $lb ) { |
240 | | - if ( session_id() != '' && $lb->getServerCount() > 1 ) { |
241 | | - $masterName = $lb->getServerName( 0 ); |
242 | | - if ( !isset( $this->shutdownPos[$masterName] ) ) { |
243 | | - $pos = $lb->getMasterPos(); |
244 | | - $info = $lb->parentInfo(); |
245 | | - wfDebug( __METHOD__.": LB " . $info['id'] . " has master pos $pos\n" ); |
246 | | - $this->shutdownPos[$masterName] = $pos; |
247 | | - } |
| 240 | + // Don't start a session, don't bother with non-replicated setups |
| 241 | + if ( strval( session_id() ) == '' || $lb->getServerCount() <= 1 ) { |
| 242 | + return; |
248 | 243 | } |
| 244 | + $masterName = $lb->getServerName( 0 ); |
| 245 | + if ( isset( $this->shutdownPos[$masterName] ) ) { |
| 246 | + // Already done |
| 247 | + return; |
| 248 | + } |
| 249 | + // Only save the position if writes have been done on the connection |
| 250 | + $db = $lb->getAnyOpenConnection( 0 ); |
| 251 | + $info = $lb->parentInfo(); |
| 252 | + if ( !$db || !$db->doneWrites() ) { |
| 253 | + wfDebug( __METHOD__.": LB {$info['id']}, no writes done\n" ); |
| 254 | + return; |
| 255 | + } |
| 256 | + $pos = $db->getMasterPos(); |
| 257 | + wfDebug( __METHOD__.": LB {$info['id']} has master pos $pos\n" ); |
| 258 | + $this->shutdownPos[$masterName] = $pos; |
249 | 259 | } |
250 | 260 | |
251 | 261 | /** |
Index: trunk/phase3/includes/db/LoadBalancer.php |
— | — | @@ -824,7 +824,7 @@ |
825 | 825 | continue; |
826 | 826 | } |
827 | 827 | foreach ( $conns2[$masterIndex] as $conn ) { |
828 | | - if ( $conn->lastQuery() != '' ) { |
| 828 | + if ( $conn->doneWrites() ) { |
829 | 829 | $conn->commit(); |
830 | 830 | } |
831 | 831 | } |