From db170ebe78a9888b4966cc934f9571ee22ad2821 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Sun, 4 Oct 2015 22:15:33 -0700 Subject: [PATCH] Enforce lagged-slave read-only mode on the DB layer * Most callers gracefully check wfReadOnly(), but fail in case they dont. This also catches foreign DBs which might slip through the cracks. * Also remove useless wfDebug() call around mDoneWrites check as write queries show in the logs anyway. Change-Id: I560ebd19c4eb2b3a040d4331702346440617cfaa --- autoload.php | 1 + includes/db/Database.php | 6 +++--- includes/db/DatabaseError.php | 6 ++++++ includes/db/loadbalancer/LoadBalancer.php | 8 ++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/autoload.php b/autoload.php index 9c859b7d18..46f592aca3 100644 --- a/autoload.php +++ b/autoload.php @@ -287,6 +287,7 @@ $wgAutoloadLocalClasses = array( 'DBLockManager' => __DIR__ . '/includes/filebackend/lockmanager/DBLockManager.php', 'DBMasterPos' => __DIR__ . '/includes/db/DatabaseUtility.php', 'DBQueryError' => __DIR__ . '/includes/db/DatabaseError.php', + 'DBReadOnlyError' => __DIR__ . '/includes/db/DatabaseError.php', 'DBSiteStore' => __DIR__ . '/includes/site/DBSiteStore.php', 'DBUnexpectedError' => __DIR__ . '/includes/db/DatabaseError.php', 'DataUpdate' => __DIR__ . '/includes/deferred/DataUpdate.php', diff --git a/includes/db/Database.php b/includes/db/Database.php index 05d1934797..2c2d37f29b 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -932,9 +932,9 @@ abstract class DatabaseBase implements IDatabase { $isWriteQuery = $this->isWriteQuery( $sql ); if ( $isWriteQuery ) { - if ( !$this->mDoneWrites ) { - wfDebug( __METHOD__ . ': Writes done: ' . - DatabaseBase::generalizeSQL( $sql ) . "\n" ); + $reason = $this->getLBInfo( 'readOnlyReason' ); + if ( is_string( $reason ) ) { + throw new DBReadOnlyError( $this, "Database is read-only: $reason" ); } # Set a flag indicating that writes have been done $this->mDoneWrites = microtime( true ); diff --git a/includes/db/DatabaseError.php b/includes/db/DatabaseError.php index 928de61612..6453854a7b 100644 --- a/includes/db/DatabaseError.php +++ b/includes/db/DatabaseError.php @@ -451,3 +451,9 @@ This may indicate a bug in the software.', */ class DBUnexpectedError extends DBError { } + +/** + * @ingroup Database + */ +class DBReadOnlyError extends DBError { +} diff --git a/includes/db/loadbalancer/LoadBalancer.php b/includes/db/loadbalancer/LoadBalancer.php index a0ef753b42..cd3b006528 100644 --- a/includes/db/loadbalancer/LoadBalancer.php +++ b/includes/db/loadbalancer/LoadBalancer.php @@ -546,6 +546,14 @@ class LoadBalancer { $trxProf->recordConnection( $host, $dbname, $masterOnly ); } + # Make master connections read only if in lagged slave mode + if ( $masterOnly && $this->getServerCount() > 1 && $this->getLaggedSlaveMode() ) { + $conn->setLBInfo( 'readOnlyReason', + 'The database has been automatically locked ' . + 'while the slave database servers catch up to the master' + ); + } + return $conn; } -- 2.20.1