Aaron Schulz has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/311591

Change subject: Avoid TransactionProfiler notices for TEMPORARY table writes
......................................................................

Avoid TransactionProfiler notices for TEMPORARY table writes

* Make Database detect and track temporary tables for the session.
  Creating, dropping, and updating them do not count as "write" queries.
  Even a read-only mysql slave can have these operations performed on it
  and it can be useful for complex read queries that need temporary results.
* Rename handleTransactionLoss() to handleSessionLoss() and cover named locks 
too.

Bug: T145947
Change-Id: I826439e9e9f550f32a9c46b3dd60e8e8015aa274
---
M includes/libs/rdbms/database/Database.php
M maintenance/sql.php
2 files changed, 52 insertions(+), 15 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/91/311591/1

diff --git a/includes/libs/rdbms/database/Database.php 
b/includes/libs/rdbms/database/Database.php
index f9e9296..55e94b7 100644
--- a/includes/libs/rdbms/database/Database.php
+++ b/includes/libs/rdbms/database/Database.php
@@ -203,6 +203,8 @@
 
        /** @var array Map of (name => 1) for locks obtained via lock() */
        private $mNamedLocksHeld = [];
+       /** @var array Map of (table name => 1) for TEMPORARY tables */
+       private $mSessionTempTables = [];
 
        /** @var IDatabase|null Lazy handle to the master DB this server 
replicates from */
        private $lazyMasterHandle;
@@ -772,11 +774,40 @@
                return !in_array( $verb, [ 'BEGIN', 'COMMIT', 'ROLLBACK', 
'SHOW', 'SET' ], true );
        }
 
+       /**
+        * @param string $sql A SQL query
+        * @return bool Whether $sql is SQL for creating/dropping a new 
TEMPORARY table
+        */
+       protected function registerTempTableOperation( $sql ) {
+               if ( preg_match(
+                       
'/^(CREATE|DROP)\s+TEMPORARY\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"\']?(\w+)[`"\']?/i',
+                       $sql,
+                       $matches
+               ) ) {
+                       list( , $verb, $table ) = $matches;
+                       if ( $verb === 'CREATE' ) {
+                               $this->mSessionTempTables[$table] = 1;
+                       } else {
+                               unset( $this->mSessionTempTables[$table] );
+                       }
+
+                       return true;
+               } elseif ( preg_match(
+                       
'/^(?:INSERT\s+INTO|REPLACE\s+INTO|UPDATE|DELETE\s+FROM)\s+[`"\']?(\w+)[`"\']?/i',
+                       $sql,
+                       $matches
+               ) ) {
+                       return isset( $this->mSessionTempTables[$matches[1]] );
+               }
+
+               return false;
+       }
+
        public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) 
{
                $priorWritesPending = $this->writesOrCallbacksPending();
                $this->mLastQuery = $sql;
 
-               $isWrite = $this->isWriteQuery( $sql );
+               $isWrite = $this->isWriteQuery( $sql ) && 
!$this->registerTempTableOperation( $sql );
                if ( $isWrite ) {
                        $reason = $this->getReadOnlyReason();
                        if ( $reason !== false ) {
@@ -822,7 +853,7 @@
                        $lastError = $this->lastError();
                        $lastErrno = $this->lastErrno();
                        # Update state tracking to reflect transaction loss due 
to disconnection
-                       $this->handleTransactionLoss();
+                       $this->handleSessionLoss();
                        if ( $this->reconnect() ) {
                                $msg = __METHOD__ . ": lost connection to 
{$this->getServer()}; reconnected";
                                $this->connLogger->warning( $msg );
@@ -851,7 +882,7 @@
                                        $tempIgnore = false; // not recoverable
                                }
                                # Update state tracking to reflect transaction 
loss
-                               $this->handleTransactionLoss();
+                               $this->handleSessionLoss();
                        }
 
                        $this->reportQueryError(
@@ -964,10 +995,12 @@
                return true;
        }
 
-       private function handleTransactionLoss() {
+       private function handleSessionLoss() {
                $this->mTrxLevel = 0;
                $this->mTrxIdleCallbacks = []; // bug 65263
                $this->mTrxPreCommitCallbacks = []; // bug 65263
+               $this->mSessionTempTables = [];
+               $this->mNamedLocksHeld = [];
                try {
                        // Handle callbacks in mTrxEndCallbacks
                        $this->runOnTransactionIdleCallbacks( 
self::TRIGGER_ROLLBACK );
diff --git a/maintenance/sql.php b/maintenance/sql.php
index e6a30a3..a9fe45a 100644
--- a/maintenance/sql.php
+++ b/maintenance/sql.php
@@ -44,6 +44,8 @@
        }
 
        public function execute() {
+               global $IP;
+
                // We wan't to allow "" for the wikidb, meaning don't call 
select_db()
                $wiki = $this->hasOption( 'wikidb' ) ? $this->getOption( 
'wikidb' ) : false;
                // Get the appropriate load balancer (for this wiki)
@@ -66,12 +68,13 @@
                                }
                        }
                        if ( $index === null ) {
-                               $this->error( "No replica DB server configured 
with the name '$server'.", 1 );
+                               $this->error( "No replica DB server configured 
with the name '$replicaDB'.", 1 );
                        }
                } else {
                        $index = DB_MASTER;
                }
-               // Get a DB handle (with this wiki's DB selected) from the 
appropriate load balancer
+
+               /** @var Database $db DB handle for the appropriate 
cluster/wiki */
                $db = $lb->getConnection( $index, [], $wiki );
                if ( $replicaDB != '' && $db->getLBInfo( 'master' ) !== null ) {
                        $this->error( "The server selected ({$db->getServer()}) 
is not a replica DB.", 1 );
@@ -98,14 +101,15 @@
                        return;
                }
 
-               $useReadline = function_exists( 'readline_add_history' )
-                       && Maintenance::posix_isatty( 0 /*STDIN*/ );
-
-               if ( $useReadline ) {
-                       global $IP;
+               if (
+                       function_exists( 'readline_add_history' ) &&
+                       Maintenance::posix_isatty( 0 /*STDIN*/ )
+               ) {
                        $historyFile = isset( $_ENV['HOME'] ) ?
                                "{$_ENV['HOME']}/.mwsql_history" : 
"$IP/maintenance/.mwsql_history";
                        readline_read_history( $historyFile );
+               } else {
+                       $historyFile = null;
                }
 
                $wholeLine = '';
@@ -126,10 +130,10 @@
                                $prompt = '    -> ';
                                continue;
                        }
-                       if ( $useReadline ) {
+                       if ( $historyFile ) {
                                # Delimiter is eated by streamStatementEnd, we 
add it
                                # up in the history (bug 37020)
-                               readline_add_history( $wholeLine . 
$db->getDelimiter() );
+                               readline_add_history( $wholeLine . ';' );
                                readline_write_history( $historyFile );
                        }
                        $this->sqlDoQuery( $db, $wholeLine, $doDie );
@@ -139,7 +143,7 @@
                wfWaitForSlaves();
        }
 
-       protected function sqlDoQuery( $db, $line, $dieOnError ) {
+       protected function sqlDoQuery( IDatabase $db, $line, $dieOnError ) {
                try {
                        $res = $db->query( $line );
                        $this->sqlPrintResult( $res, $db );
@@ -151,7 +155,7 @@
        /**
         * Print the results, callback for $db->sourceStream()
         * @param ResultWrapper $res The results object
-        * @param DatabaseBase $db
+        * @param IDatabase $db
         */
        public function sqlPrintResult( $res, $db ) {
                if ( !$res ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/311591
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I826439e9e9f550f32a9c46b3dd60e8e8015aa274
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <asch...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to